1 /*
2 ** Copyright (C) 2002-2018 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 /*
20 **	Utility functions to make writing the test suite easier.
21 **
22 **	The .c and .h files were generated automagically with Autogen from
23 **	the files utils.def and utils.tpl.
24 */
25 
26 
27 
28 #include "sfconfig.h"
29 
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <inttypes.h>
33 
34 #if HAVE_UNISTD_H
35 #include <unistd.h>
36 #endif
37 
38 #if (HAVE_DECL_S_IRGRP == 0)
39 #include <sf_unistd.h>
40 #endif
41 
42 #include <errno.h>
43 #include <string.h>
44 #include <ctype.h>
45 #include <math.h>
46 #include <fcntl.h>
47 #include <sys/stat.h>
48 
49 #include <sndfile.h>
50 
51 #include "utils.h"
52 
53 #ifndef	M_PI
54 #define	M_PI		3.14159265358979323846264338
55 #endif
56 
57 #define	LOG_BUFFER_SIZE		4096
58 
59 /*
60 **	Neat solution to the Win32/OS2 binary file flage requirement.
61 **	If O_BINARY isn't already defined by the inclusion of the system
62 **	headers, set it to zero.
63 */
64 #ifndef O_BINARY
65 #define O_BINARY 0
66 #endif
67 
68 
69 void
gen_windowed_sine_float(float * data,int len,double maximum)70 gen_windowed_sine_float (float *data, int len, double maximum)
71 {	int k ;
72 
73 	memset (data, 0, len * sizeof (float)) ;
74 
75 	len = (5 * len) / 6 ;
76 
77 	for (k = 0 ; k < len ; k++)
78 	{	data [k] = sin (2.0 * k * M_PI * 1.0 / 32.0 + 0.4) ;
79 
80 		/* Apply Hanning Window. */
81 		data [k] *= maximum * (0.5 - 0.5 * cos (2.0 * M_PI * k / ((len) - 1))) ;
82 		}
83 
84 	return ;
85 } /* gen_windowed_sine_float */
86 
87 void
gen_windowed_sine_double(double * data,int len,double maximum)88 gen_windowed_sine_double (double *data, int len, double maximum)
89 {	int k ;
90 
91 	memset (data, 0, len * sizeof (double)) ;
92 
93 	len = (5 * len) / 6 ;
94 
95 	for (k = 0 ; k < len ; k++)
96 	{	data [k] = sin (2.0 * k * M_PI * 1.0 / 32.0 + 0.4) ;
97 
98 		/* Apply Hanning Window. */
99 		data [k] *= maximum * (0.5 - 0.5 * cos (2.0 * M_PI * k / ((len) - 1))) ;
100 		}
101 
102 	return ;
103 } /* gen_windowed_sine_double */
104 
105 
106 void
create_short_sndfile(const char * filename,int format,int channels)107 create_short_sndfile (const char *filename, int format, int channels)
108 {	short data [2 * 3 * 4 * 5 * 6 * 7] = { 0, } ;
109 	SNDFILE *file ;
110 	SF_INFO sfinfo ;
111 
112 	memset (&sfinfo, 0, sizeof (sfinfo)) ;
113 	sfinfo.samplerate = 44100 ;
114 	sfinfo.channels = channels ;
115 	sfinfo.format = format ;
116 
117 	if ((file = sf_open (filename, SFM_WRITE, &sfinfo)) == NULL)
118 	{	printf ("Error (%s, %d) : sf_open failed : %s\n", __FILE__, __LINE__, sf_strerror (file)) ;
119 		exit (1) ;
120 		} ;
121 
122 	sf_write_short (file, data, ARRAY_LEN (data)) ;
123 
124 	sf_close (file) ;
125 } /* create_short_sndfile */
126 
127 void
check_file_hash_or_die(const char * filename,uint64_t target_hash,int line_num)128 check_file_hash_or_die (const char *filename, uint64_t target_hash, int line_num)
129 {	static unsigned char buf [4096] ;
130 	uint64_t	cksum ;
131 	FILE 		*file ;
132 	int			k, read_count ;
133 
134 	memset (buf, 0, sizeof (buf)) ;
135 
136 	/* The 'b' in the mode string means binary for Win32. */
137 	if ((file = fopen (filename, "rb")) == NULL)
138 	{	printf ("\n\nLine %d: could not open file '%s'\n\n", line_num, filename) ;
139 		exit (1) ;
140 		} ;
141 
142 	cksum = 0 ;
143 
144 	while ((read_count = fread (buf, 1, sizeof (buf), file)))
145 		for (k = 0 ; k < read_count ; k++)
146 			cksum = (cksum * 511 + buf [k]) & 0xfffffffffffff ;
147 
148 	fclose (file) ;
149 
150 	if (target_hash == 0)
151 	{	printf (" 0x%" PRIx64 "\n", cksum) ;
152 		return ;
153 		} ;
154 
155 	if (cksum != target_hash)
156 	{	printf ("\n\nLine %d: incorrect hash value 0x%" PRIx64 " should be 0x%" PRIx64 ".\n\n", line_num, cksum, target_hash) ;
157 		exit (1) ;
158 		} ;
159 
160 	return ;
161 } /* check_file_hash_or_die */
162 
163 void
print_test_name(const char * test,const char * filename)164 print_test_name (const char *test, const char *filename)
165 {	int count ;
166 
167 	if (test == NULL)
168 	{	printf (__FILE__ ": bad test of filename parameter.\n") ;
169 		exit (1) ;
170 		} ;
171 
172 	if (filename == NULL || strlen (filename) == 0)
173 	{	printf ("    %-30s : ", test) ;
174 		count = 25 ;
175 		}
176 	else
177 	{	printf ("    %-30s : %s ", test, filename) ;
178 		count = 24 - strlen (filename) ;
179 		} ;
180 
181 	while (count -- > 0)
182 		putchar ('.') ;
183 	putchar (' ') ;
184 
185 	fflush (stdout) ;
186 } /* print_test_name */
187 
188 void
dump_data_to_file(const char * filename,const void * data,unsigned int datalen)189 dump_data_to_file (const char *filename, const void *data, unsigned int datalen)
190 {	FILE *file ;
191 
192 	if ((file = fopen (filename, "wb")) == NULL)
193 	{	printf ("\n\nLine %d : could not open file : %s\n\n", __LINE__, filename) ;
194 		exit (1) ;
195 		} ;
196 
197 	if (fwrite (data, 1, datalen, file) != datalen)
198 	{	printf ("\n\nLine %d : fwrite failed.\n\n", __LINE__) ;
199 		exit (1) ;
200 		} ;
201 
202 	fclose (file) ;
203 
204 } /* dump_data_to_file */
205 
206 /*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
207 */
208 
209 static char octfilename [] = "error.dat" ;
210 
211 int
oct_save_short(const short * a,const short * b,int len)212 oct_save_short	(const short *a, const short *b, int len)
213 {	FILE 	*file ;
214 	int		k ;
215 
216 	if (! (file = fopen (octfilename, "w")))
217 		return 1 ;
218 
219 	fprintf (file, "# Not created by Octave\n") ;
220 
221 	fprintf (file, "# name: a\n") ;
222 	fprintf (file, "# type: matrix\n") ;
223 	fprintf (file, "# rows: %d\n", len) ;
224 	fprintf (file, "# columns: 1\n") ;
225 
226 	for (k = 0 ; k < len ; k++)
227 		fprintf (file, "% d" "\n", a [k]) ;
228 
229 	fprintf (file, "# name: b\n") ;
230 	fprintf (file, "# type: matrix\n") ;
231 	fprintf (file, "# rows: %d\n", len) ;
232 	fprintf (file, "# columns: 1\n") ;
233 
234 	for (k = 0 ; k < len ; k++)
235 		fprintf (file, "% d" "\n", b [k]) ;
236 
237 	fclose (file) ;
238 	return 0 ;
239 } /* oct_save_short */
240 int
oct_save_int(const int * a,const int * b,int len)241 oct_save_int	(const int *a, const int *b, int len)
242 {	FILE 	*file ;
243 	int		k ;
244 
245 	if (! (file = fopen (octfilename, "w")))
246 		return 1 ;
247 
248 	fprintf (file, "# Not created by Octave\n") ;
249 
250 	fprintf (file, "# name: a\n") ;
251 	fprintf (file, "# type: matrix\n") ;
252 	fprintf (file, "# rows: %d\n", len) ;
253 	fprintf (file, "# columns: 1\n") ;
254 
255 	for (k = 0 ; k < len ; k++)
256 		fprintf (file, "% d" "\n", a [k]) ;
257 
258 	fprintf (file, "# name: b\n") ;
259 	fprintf (file, "# type: matrix\n") ;
260 	fprintf (file, "# rows: %d\n", len) ;
261 	fprintf (file, "# columns: 1\n") ;
262 
263 	for (k = 0 ; k < len ; k++)
264 		fprintf (file, "% d" "\n", b [k]) ;
265 
266 	fclose (file) ;
267 	return 0 ;
268 } /* oct_save_int */
269 int
oct_save_float(const float * a,const float * b,int len)270 oct_save_float	(const float *a, const float *b, int len)
271 {	FILE 	*file ;
272 	int		k ;
273 
274 	if (! (file = fopen (octfilename, "w")))
275 		return 1 ;
276 
277 	fprintf (file, "# Not created by Octave\n") ;
278 
279 	fprintf (file, "# name: a\n") ;
280 	fprintf (file, "# type: matrix\n") ;
281 	fprintf (file, "# rows: %d\n", len) ;
282 	fprintf (file, "# columns: 1\n") ;
283 
284 	for (k = 0 ; k < len ; k++)
285 		fprintf (file, "% g" "\n", a [k]) ;
286 
287 	fprintf (file, "# name: b\n") ;
288 	fprintf (file, "# type: matrix\n") ;
289 	fprintf (file, "# rows: %d\n", len) ;
290 	fprintf (file, "# columns: 1\n") ;
291 
292 	for (k = 0 ; k < len ; k++)
293 		fprintf (file, "% g" "\n", b [k]) ;
294 
295 	fclose (file) ;
296 	return 0 ;
297 } /* oct_save_float */
298 int
oct_save_double(const double * a,const double * b,int len)299 oct_save_double	(const double *a, const double *b, int len)
300 {	FILE 	*file ;
301 	int		k ;
302 
303 	if (! (file = fopen (octfilename, "w")))
304 		return 1 ;
305 
306 	fprintf (file, "# Not created by Octave\n") ;
307 
308 	fprintf (file, "# name: a\n") ;
309 	fprintf (file, "# type: matrix\n") ;
310 	fprintf (file, "# rows: %d\n", len) ;
311 	fprintf (file, "# columns: 1\n") ;
312 
313 	for (k = 0 ; k < len ; k++)
314 		fprintf (file, "% g" "\n", a [k]) ;
315 
316 	fprintf (file, "# name: b\n") ;
317 	fprintf (file, "# type: matrix\n") ;
318 	fprintf (file, "# rows: %d\n", len) ;
319 	fprintf (file, "# columns: 1\n") ;
320 
321 	for (k = 0 ; k < len ; k++)
322 		fprintf (file, "% g" "\n", b [k]) ;
323 
324 	fclose (file) ;
325 	return 0 ;
326 } /* oct_save_double */
327 
328 
329 void
check_log_buffer_or_die(SNDFILE * file,int line_num)330 check_log_buffer_or_die (SNDFILE *file, int line_num)
331 {	static char	buffer [LOG_BUFFER_SIZE] ;
332 	int			count ;
333 
334 	memset (buffer, 0, sizeof (buffer)) ;
335 
336 	/* Get the log buffer data. */
337 	count = sf_command	(file, SFC_GET_LOG_INFO, buffer, LOG_BUFFER_SIZE) ;
338 
339 	if (LOG_BUFFER_SIZE - count < 2)
340 	{	printf ("\n\nLine %d : Possible long log buffer.\n", line_num) ;
341 		exit (1) ;
342 		}
343 
344 	/* Look for "Should" */
345 	if (strstr (buffer, "ould"))
346 	{	printf ("\n\nLine %d : Log buffer contains `ould'. Dumping.\n", line_num) ;
347 		puts (buffer) ;
348 		exit (1) ;
349 		} ;
350 
351 	/* Look for "**" */
352 	if (strstr (buffer, "*"))
353 	{	printf ("\n\nLine %d : Log buffer contains `*'. Dumping.\n", line_num) ;
354 		puts (buffer) ;
355 		exit (1) ;
356 		} ;
357 
358 	/* Look for "Should" */
359 	if (strstr (buffer, "nknown marker"))
360 	{	printf ("\n\nLine %d : Log buffer contains `nknown marker'. Dumping.\n", line_num) ;
361 		puts (buffer) ;
362 		exit (1) ;
363 		} ;
364 
365 	return ;
366 } /* check_log_buffer_or_die */
367 
368 int
string_in_log_buffer(SNDFILE * file,const char * s)369 string_in_log_buffer (SNDFILE *file, const char *s)
370 {	static char	buffer [LOG_BUFFER_SIZE] ;
371 	int			count ;
372 
373 	memset (buffer, 0, sizeof (buffer)) ;
374 
375 	/* Get the log buffer data. */
376 	count = sf_command	(file, SFC_GET_LOG_INFO, buffer, LOG_BUFFER_SIZE) ;
377 
378 	if (LOG_BUFFER_SIZE - count < 2)
379 	{	printf ("Possible long log buffer.\n") ;
380 		exit (1) ;
381 		}
382 
383 	/* Look for string */
384 	return strstr (buffer, s) ? SF_TRUE : SF_FALSE ;
385 } /* string_in_log_buffer */
386 
387 void
hexdump_file(const char * filename,sf_count_t offset,sf_count_t length)388 hexdump_file (const char * filename, sf_count_t offset, sf_count_t length)
389 {
390 	FILE * file ;
391 	char buffer [16] ;
392 	int k, m, ch, readcount ;
393 
394 	if (length > 1000000)
395 	{	printf ("\n\nError : length (%" PRId64 ") too long.\n\n", offset) ;
396 		exit (1) ;
397 		} ;
398 
399 	if ((file = fopen (filename, "r")) == NULL)
400 	{	printf ("\n\nError : hexdump_file (%s) could not open file for read.\n\n", filename) ;
401 		exit (1) ;
402 		} ;
403 
404 	if (fseek (file, offset, SEEK_SET) != 0)
405 	{	printf ("\n\nError : fseek(file, %" PRId64 ", SEEK_SET) failed : %s\n\n", offset, strerror (errno)) ;
406 		exit (1) ;
407 		} ;
408 
409 	puts ("\n\n") ;
410 
411 	for (k = 0 ; k < length ; k+= sizeof (buffer))
412 	{	readcount = fread (buffer, 1, sizeof (buffer), file) ;
413 
414 		printf ("%08" PRIx64 " : ", offset + k) ;
415 
416 		for (m = 0 ; m < readcount ; m++)
417 			printf ("%02x ", buffer [m] & 0xFF) ;
418 
419 		for (m = readcount ; m < SIGNED_SIZEOF (buffer) ; m++)
420 			printf ("   ") ;
421 
422 		printf ("  ") ;
423 		for (m = 0 ; m < readcount ; m++)
424 		{	ch = isprint (buffer [m]) ? buffer [m] : '.' ;
425 			putchar (ch) ;
426 			} ;
427 
428 		if (readcount < SIGNED_SIZEOF (buffer))
429 			break ;
430 
431 		putchar ('\n') ;
432 		} ;
433 
434 	puts ("\n") ;
435 
436 	fclose (file) ;
437 } /* hexdump_file */
438 
439 void
dump_log_buffer(SNDFILE * file)440 dump_log_buffer (SNDFILE *file)
441 {	static char	buffer [LOG_BUFFER_SIZE] ;
442 
443 	memset (buffer, 0, sizeof (buffer)) ;
444 
445 	/* Get the log buffer data. */
446 	sf_command	(file, SFC_GET_LOG_INFO, buffer, LOG_BUFFER_SIZE) ;
447 
448 	if (strlen (buffer) < 1)
449 		puts ("Log buffer empty.\n") ;
450 	else
451 		puts (buffer) ;
452 
453 	return ;
454 } /* dump_log_buffer */
455 
456 void
test_sf_format_or_die(const SF_INFO * info,int line_num)457 test_sf_format_or_die (const SF_INFO *info, int line_num)
458 {	int res ;
459 
460 	if ((res = sf_format_check (info)) != 1)
461 	{	printf ("\n\nLine %d : sf_format_check returned error (%d)\n\n", line_num, res) ;
462 		exit (1) ;
463 		} ;
464 
465 	return ;
466 } /* test_sf_format_or_die */
467 
468 SNDFILE *
test_open_file_or_die(const char * filename,int mode,SF_INFO * sfinfo,int allow_fd,int line_num)469 test_open_file_or_die (const char *filename, int mode, SF_INFO *sfinfo, int allow_fd, int line_num)
470 {	static int count = 0 ;
471 
472 	SNDFILE *file ;
473 	const char *modestr, *func_name ;
474 	int oflags = 0, omode = 0, err ;
475 
476 	/*
477 	** Need to test both sf_open() and sf_open_fd().
478 	** Do so alternately.
479 	*/
480 	switch (mode)
481 	{	case SFM_READ :
482 				modestr = "SFM_READ" ;
483 				oflags = O_RDONLY | O_BINARY ;
484 				omode = 0 ;
485 				break ;
486 
487 		case SFM_WRITE :
488 				modestr = "SFM_WRITE" ;
489 				oflags = O_WRONLY | O_CREAT | O_TRUNC | O_BINARY ;
490 				omode = S_IRUSR | S_IWUSR | S_IRGRP ;
491 				break ;
492 
493 		case SFM_RDWR :
494 				modestr = "SFM_RDWR" ;
495 				oflags = O_RDWR | O_CREAT | O_BINARY ;
496 				omode = S_IRUSR | S_IWUSR | S_IRGRP ;
497 				break ;
498 		default :
499 				printf ("\n\nLine %d: Bad mode.\n", line_num) ;
500 				fflush (stdout) ;
501 				exit (1) ;
502 		} ;
503 
504 	if (OS_IS_WIN32)
505 	{	/* Windows does not understand and ignores the S_IRGRP flag, but Wine
506 		** gives a run time warning message, so just clear it.
507 		*/
508 		omode &= ~S_IRGRP ;
509 		} ;
510 
511 	if (allow_fd && ((++count) & 1) == 1)
512 	{	int fd ;
513 
514 		/* Only use the three argument open() function if omode != 0. */
515 		fd = (omode == 0) ? open (filename, oflags) : open (filename, oflags, omode) ;
516 
517 		if (fd < 0)
518 		{	printf ("\n\n%s : open failed : %s\n", __func__, strerror (errno)) ;
519 			exit (1) ;
520 			} ;
521 
522 		func_name = "sf_open_fd" ;
523 		file = sf_open_fd (fd, mode, sfinfo, SF_TRUE) ;
524 		}
525 	else
526 	{	func_name = "sf_open" ;
527 		file = sf_open (filename, mode, sfinfo) ;
528 		} ;
529 
530 	if (file == NULL)
531 	{	printf ("\n\nLine %d: %s (%s) failed : %s\n\n", line_num, func_name, modestr, sf_strerror (NULL)) ;
532 		dump_log_buffer (file) ;
533 		exit (1) ;
534 		} ;
535 
536 	err = sf_error (file) ;
537 	if (err != SF_ERR_NO_ERROR)
538 	{	printf ("\n\nLine %d : sf_error : %s\n\n", line_num, sf_error_number (err)) ;
539 		dump_log_buffer (file) ;
540 		exit (1) ;
541 		} ;
542 
543 	return file ;
544 } /* test_open_file_or_die */
545 
546 void
test_read_write_position_or_die(SNDFILE * file,int line_num,int pass,sf_count_t read_pos,sf_count_t write_pos)547 test_read_write_position_or_die (SNDFILE *file, int line_num, int pass, sf_count_t read_pos, sf_count_t write_pos)
548 {	sf_count_t pos ;
549 
550 	/* Check the current read position. */
551 	if (read_pos >= 0 && (pos = sf_seek (file, 0, SEEK_CUR | SFM_READ)) != read_pos)
552 	{	printf ("\n\nLine %d ", line_num) ;
553 		if (pass > 0)
554 			printf ("(pass %d): ", pass) ;
555 		printf ("Read position (%" PRId64 ") should be %" PRId64 ".\n", pos, read_pos) ;
556 		exit (1) ;
557 		} ;
558 
559 	/* Check the current write position. */
560 	if (write_pos >= 0 && (pos = sf_seek (file, 0, SEEK_CUR | SFM_WRITE)) != write_pos)
561 	{	printf ("\n\nLine %d", line_num) ;
562 		if (pass > 0)
563 			printf (" (pass %d)", pass) ;
564 		printf (" : Write position (%" PRId64 ") should be %" PRId64 ".\n", pos, write_pos) ;
565 		exit (1) ;
566 		} ;
567 
568 	return ;
569 } /* test_read_write_position */
570 
571 void
test_seek_or_die(SNDFILE * file,sf_count_t offset,int whence,sf_count_t new_pos,int channels,int line_num)572 test_seek_or_die (SNDFILE *file, sf_count_t offset, int whence, sf_count_t new_pos, int channels, int line_num)
573 {	sf_count_t	position ;
574 	const char	*channel_name, *whence_name ;
575 
576 	switch (whence)
577 	{	case SEEK_SET :
578 				whence_name = "SEEK_SET" ;
579 				break ;
580 		case SEEK_CUR :
581 				whence_name = "SEEK_CUR" ;
582 				break ;
583 		case SEEK_END :
584 				whence_name = "SEEK_END" ;
585 				break ;
586 
587 		/* SFM_READ */
588 		case SEEK_SET | SFM_READ :
589 				whence_name = "SFM_READ | SEEK_SET" ;
590 				break ;
591 		case SEEK_CUR | SFM_READ :
592 				whence_name = "SFM_READ | SEEK_CUR" ;
593 				break ;
594 		case SEEK_END | SFM_READ :
595 				whence_name = "SFM_READ | SEEK_END" ;
596 				break ;
597 
598 		/* SFM_WRITE */
599 		case SEEK_SET | SFM_WRITE :
600 				whence_name = "SFM_WRITE | SEEK_SET" ;
601 				break ;
602 		case SEEK_CUR | SFM_WRITE :
603 				whence_name = "SFM_WRITE | SEEK_CUR" ;
604 				break ;
605 		case SEEK_END | SFM_WRITE :
606 				whence_name = "SFM_WRITE | SEEK_END" ;
607 				break ;
608 
609 		default :
610 				printf ("\n\nLine %d: bad whence parameter.\n", line_num) ;
611 				exit (1) ;
612 		} ;
613 
614 	channel_name = (channels == 1) ? "Mono" : "Stereo" ;
615 
616 	if ((position = sf_seek (file, offset, whence)) != new_pos)
617 	{	printf ("\n\nLine %d : %s : sf_seek (file, %" PRId64 ", %s) returned %" PRId64 " (should be %" PRId64 ").\n\n",
618 					line_num, channel_name, offset, whence_name, position, new_pos) ;
619 		exit (1) ;
620 		} ;
621 
622 } /* test_seek_or_die */
623 
624 
625 
626 void
test_read_short_or_die(SNDFILE * file,int pass,short * test,sf_count_t items,int line_num)627 test_read_short_or_die (SNDFILE *file, int pass, short *test, sf_count_t items, int line_num)
628 {	sf_count_t count ;
629 
630 	if ((count = sf_read_short (file, test, items)) != items)
631 	{	printf ("\n\nLine %d", line_num) ;
632 		if (pass > 0)
633 			printf (" (pass %d)", pass) ;
634 		printf (" : sf_read_short failed with short read (%" PRId64 " => %" PRId64 ").\n",
635 						items, count) ;
636 		fflush (stdout) ;
637 		puts (sf_strerror (file)) ;
638 		exit (1) ;
639 		} ;
640 
641 	return ;
642 } /* test_read_short_or_die */
643 
644 void
test_read_int_or_die(SNDFILE * file,int pass,int * test,sf_count_t items,int line_num)645 test_read_int_or_die (SNDFILE *file, int pass, int *test, sf_count_t items, int line_num)
646 {	sf_count_t count ;
647 
648 	if ((count = sf_read_int (file, test, items)) != items)
649 	{	printf ("\n\nLine %d", line_num) ;
650 		if (pass > 0)
651 			printf (" (pass %d)", pass) ;
652 		printf (" : sf_read_int failed with short read (%" PRId64 " => %" PRId64 ").\n",
653 						items, count) ;
654 		fflush (stdout) ;
655 		puts (sf_strerror (file)) ;
656 		exit (1) ;
657 		} ;
658 
659 	return ;
660 } /* test_read_int_or_die */
661 
662 void
test_read_float_or_die(SNDFILE * file,int pass,float * test,sf_count_t items,int line_num)663 test_read_float_or_die (SNDFILE *file, int pass, float *test, sf_count_t items, int line_num)
664 {	sf_count_t count ;
665 
666 	if ((count = sf_read_float (file, test, items)) != items)
667 	{	printf ("\n\nLine %d", line_num) ;
668 		if (pass > 0)
669 			printf (" (pass %d)", pass) ;
670 		printf (" : sf_read_float failed with short read (%" PRId64 " => %" PRId64 ").\n",
671 						items, count) ;
672 		fflush (stdout) ;
673 		puts (sf_strerror (file)) ;
674 		exit (1) ;
675 		} ;
676 
677 	return ;
678 } /* test_read_float_or_die */
679 
680 void
test_read_double_or_die(SNDFILE * file,int pass,double * test,sf_count_t items,int line_num)681 test_read_double_or_die (SNDFILE *file, int pass, double *test, sf_count_t items, int line_num)
682 {	sf_count_t count ;
683 
684 	if ((count = sf_read_double (file, test, items)) != items)
685 	{	printf ("\n\nLine %d", line_num) ;
686 		if (pass > 0)
687 			printf (" (pass %d)", pass) ;
688 		printf (" : sf_read_double failed with short read (%" PRId64 " => %" PRId64 ").\n",
689 						items, count) ;
690 		fflush (stdout) ;
691 		puts (sf_strerror (file)) ;
692 		exit (1) ;
693 		} ;
694 
695 	return ;
696 } /* test_read_double_or_die */
697 
698 
699 void
test_readf_short_or_die(SNDFILE * file,int pass,short * test,sf_count_t frames,int line_num)700 test_readf_short_or_die (SNDFILE *file, int pass, short *test, sf_count_t frames, int line_num)
701 {	sf_count_t count ;
702 
703 	if ((count = sf_readf_short (file, test, frames)) != frames)
704 	{	printf ("\n\nLine %d", line_num) ;
705 		if (pass > 0)
706 			printf (" (pass %d)", pass) ;
707 		printf (" : sf_readf_short failed with short readf (%" PRId64 " => %" PRId64 ").\n",
708 						frames, count) ;
709 		fflush (stdout) ;
710 		puts (sf_strerror (file)) ;
711 		exit (1) ;
712 		} ;
713 
714 	return ;
715 } /* test_readf_short_or_die */
716 
717 void
test_readf_int_or_die(SNDFILE * file,int pass,int * test,sf_count_t frames,int line_num)718 test_readf_int_or_die (SNDFILE *file, int pass, int *test, sf_count_t frames, int line_num)
719 {	sf_count_t count ;
720 
721 	if ((count = sf_readf_int (file, test, frames)) != frames)
722 	{	printf ("\n\nLine %d", line_num) ;
723 		if (pass > 0)
724 			printf (" (pass %d)", pass) ;
725 		printf (" : sf_readf_int failed with short readf (%" PRId64 " => %" PRId64 ").\n",
726 						frames, count) ;
727 		fflush (stdout) ;
728 		puts (sf_strerror (file)) ;
729 		exit (1) ;
730 		} ;
731 
732 	return ;
733 } /* test_readf_int_or_die */
734 
735 void
test_readf_float_or_die(SNDFILE * file,int pass,float * test,sf_count_t frames,int line_num)736 test_readf_float_or_die (SNDFILE *file, int pass, float *test, sf_count_t frames, int line_num)
737 {	sf_count_t count ;
738 
739 	if ((count = sf_readf_float (file, test, frames)) != frames)
740 	{	printf ("\n\nLine %d", line_num) ;
741 		if (pass > 0)
742 			printf (" (pass %d)", pass) ;
743 		printf (" : sf_readf_float failed with short readf (%" PRId64 " => %" PRId64 ").\n",
744 						frames, count) ;
745 		fflush (stdout) ;
746 		puts (sf_strerror (file)) ;
747 		exit (1) ;
748 		} ;
749 
750 	return ;
751 } /* test_readf_float_or_die */
752 
753 void
test_readf_double_or_die(SNDFILE * file,int pass,double * test,sf_count_t frames,int line_num)754 test_readf_double_or_die (SNDFILE *file, int pass, double *test, sf_count_t frames, int line_num)
755 {	sf_count_t count ;
756 
757 	if ((count = sf_readf_double (file, test, frames)) != frames)
758 	{	printf ("\n\nLine %d", line_num) ;
759 		if (pass > 0)
760 			printf (" (pass %d)", pass) ;
761 		printf (" : sf_readf_double failed with short readf (%" PRId64 " => %" PRId64 ").\n",
762 						frames, count) ;
763 		fflush (stdout) ;
764 		puts (sf_strerror (file)) ;
765 		exit (1) ;
766 		} ;
767 
768 	return ;
769 } /* test_readf_double_or_die */
770 
771 
772 void
test_read_raw_or_die(SNDFILE * file,int pass,void * test,sf_count_t items,int line_num)773 test_read_raw_or_die (SNDFILE *file, int pass, void *test, sf_count_t items, int line_num)
774 {	sf_count_t count ;
775 
776 	if ((count = sf_read_raw (file, test, items)) != items)
777 	{	printf ("\n\nLine %d", line_num) ;
778 		if (pass > 0)
779 			printf (" (pass %d)", pass) ;
780 		printf (" : sf_read_raw failed with short read (%" PRId64 " => %" PRId64 ").\n", items, count) ;
781 		fflush (stdout) ;
782 		puts (sf_strerror (file)) ;
783 		exit (1) ;
784 		} ;
785 
786 	return ;
787 } /* test_read_raw_or_die */
788 
789 
790 
791 void
test_write_short_or_die(SNDFILE * file,int pass,const short * test,sf_count_t items,int line_num)792 test_write_short_or_die (SNDFILE *file, int pass, const short *test, sf_count_t items, int line_num)
793 {	sf_count_t count ;
794 
795 	if ((count = sf_write_short (file, test, items)) != items)
796 	{	printf ("\n\nLine %d", line_num) ;
797 		if (pass > 0)
798 			printf (" (pass %d)", pass) ;
799 		printf (" : sf_write_short failed with short write (%" PRId64 " => %" PRId64 ").\n",
800 						items, count) ;
801 		fflush (stdout) ;
802 		puts (sf_strerror (file)) ;
803 		exit (1) ;
804 		} ;
805 
806 	return ;
807 } /* test_write_short_or_die */
808 
809 void
test_write_int_or_die(SNDFILE * file,int pass,const int * test,sf_count_t items,int line_num)810 test_write_int_or_die (SNDFILE *file, int pass, const int *test, sf_count_t items, int line_num)
811 {	sf_count_t count ;
812 
813 	if ((count = sf_write_int (file, test, items)) != items)
814 	{	printf ("\n\nLine %d", line_num) ;
815 		if (pass > 0)
816 			printf (" (pass %d)", pass) ;
817 		printf (" : sf_write_int failed with short write (%" PRId64 " => %" PRId64 ").\n",
818 						items, count) ;
819 		fflush (stdout) ;
820 		puts (sf_strerror (file)) ;
821 		exit (1) ;
822 		} ;
823 
824 	return ;
825 } /* test_write_int_or_die */
826 
827 void
test_write_float_or_die(SNDFILE * file,int pass,const float * test,sf_count_t items,int line_num)828 test_write_float_or_die (SNDFILE *file, int pass, const float *test, sf_count_t items, int line_num)
829 {	sf_count_t count ;
830 
831 	if ((count = sf_write_float (file, test, items)) != items)
832 	{	printf ("\n\nLine %d", line_num) ;
833 		if (pass > 0)
834 			printf (" (pass %d)", pass) ;
835 		printf (" : sf_write_float failed with short write (%" PRId64 " => %" PRId64 ").\n",
836 						items, count) ;
837 		fflush (stdout) ;
838 		puts (sf_strerror (file)) ;
839 		exit (1) ;
840 		} ;
841 
842 	return ;
843 } /* test_write_float_or_die */
844 
845 void
test_write_double_or_die(SNDFILE * file,int pass,const double * test,sf_count_t items,int line_num)846 test_write_double_or_die (SNDFILE *file, int pass, const double *test, sf_count_t items, int line_num)
847 {	sf_count_t count ;
848 
849 	if ((count = sf_write_double (file, test, items)) != items)
850 	{	printf ("\n\nLine %d", line_num) ;
851 		if (pass > 0)
852 			printf (" (pass %d)", pass) ;
853 		printf (" : sf_write_double failed with short write (%" PRId64 " => %" PRId64 ").\n",
854 						items, count) ;
855 		fflush (stdout) ;
856 		puts (sf_strerror (file)) ;
857 		exit (1) ;
858 		} ;
859 
860 	return ;
861 } /* test_write_double_or_die */
862 
863 
864 void
test_writef_short_or_die(SNDFILE * file,int pass,const short * test,sf_count_t frames,int line_num)865 test_writef_short_or_die (SNDFILE *file, int pass, const short *test, sf_count_t frames, int line_num)
866 {	sf_count_t count ;
867 
868 	if ((count = sf_writef_short (file, test, frames)) != frames)
869 	{	printf ("\n\nLine %d", line_num) ;
870 		if (pass > 0)
871 			printf (" (pass %d)", pass) ;
872 		printf (" : sf_writef_short failed with short writef (%" PRId64 " => %" PRId64 ").\n",
873 						frames, count) ;
874 		fflush (stdout) ;
875 		puts (sf_strerror (file)) ;
876 		exit (1) ;
877 		} ;
878 
879 	return ;
880 } /* test_writef_short_or_die */
881 
882 void
test_writef_int_or_die(SNDFILE * file,int pass,const int * test,sf_count_t frames,int line_num)883 test_writef_int_or_die (SNDFILE *file, int pass, const int *test, sf_count_t frames, int line_num)
884 {	sf_count_t count ;
885 
886 	if ((count = sf_writef_int (file, test, frames)) != frames)
887 	{	printf ("\n\nLine %d", line_num) ;
888 		if (pass > 0)
889 			printf (" (pass %d)", pass) ;
890 		printf (" : sf_writef_int failed with short writef (%" PRId64 " => %" PRId64 ").\n",
891 						frames, count) ;
892 		fflush (stdout) ;
893 		puts (sf_strerror (file)) ;
894 		exit (1) ;
895 		} ;
896 
897 	return ;
898 } /* test_writef_int_or_die */
899 
900 void
test_writef_float_or_die(SNDFILE * file,int pass,const float * test,sf_count_t frames,int line_num)901 test_writef_float_or_die (SNDFILE *file, int pass, const float *test, sf_count_t frames, int line_num)
902 {	sf_count_t count ;
903 
904 	if ((count = sf_writef_float (file, test, frames)) != frames)
905 	{	printf ("\n\nLine %d", line_num) ;
906 		if (pass > 0)
907 			printf (" (pass %d)", pass) ;
908 		printf (" : sf_writef_float failed with short writef (%" PRId64 " => %" PRId64 ").\n",
909 						frames, count) ;
910 		fflush (stdout) ;
911 		puts (sf_strerror (file)) ;
912 		exit (1) ;
913 		} ;
914 
915 	return ;
916 } /* test_writef_float_or_die */
917 
918 void
test_writef_double_or_die(SNDFILE * file,int pass,const double * test,sf_count_t frames,int line_num)919 test_writef_double_or_die (SNDFILE *file, int pass, const double *test, sf_count_t frames, int line_num)
920 {	sf_count_t count ;
921 
922 	if ((count = sf_writef_double (file, test, frames)) != frames)
923 	{	printf ("\n\nLine %d", line_num) ;
924 		if (pass > 0)
925 			printf (" (pass %d)", pass) ;
926 		printf (" : sf_writef_double failed with short writef (%" PRId64 " => %" PRId64 ").\n",
927 						frames, count) ;
928 		fflush (stdout) ;
929 		puts (sf_strerror (file)) ;
930 		exit (1) ;
931 		} ;
932 
933 	return ;
934 } /* test_writef_double_or_die */
935 
936 
937 void
test_write_raw_or_die(SNDFILE * file,int pass,const void * test,sf_count_t items,int line_num)938 test_write_raw_or_die (SNDFILE *file, int pass, const void *test, sf_count_t items, int line_num)
939 {	sf_count_t count ;
940 
941 	if ((count = sf_write_raw (file, test, items)) != items)
942 	{	printf ("\n\nLine %d", line_num) ;
943 		if (pass > 0)
944 			printf (" (pass %d)", pass) ;
945 		printf (" : sf_write_raw failed with short write (%" PRId64 " => %" PRId64 ").\n", items, count) ;
946 		fflush (stdout) ;
947 		puts (sf_strerror (file)) ;
948 		exit (1) ;
949 		} ;
950 
951 	return ;
952 } /* test_write_raw_or_die */
953 
954 
955 void
compare_short_or_die(const short * expected,const short * actual,unsigned count,int line_num)956 compare_short_or_die (const short *expected, const short *actual, unsigned count, int line_num)
957 {
958 	unsigned k ;
959 
960 	for (k = 0 ; k < count ; k++)
961 		if (expected [k] != actual [k])
962 		{	printf ("\n\nLine %d : Error at index %d, got " "% d" ", should be " "% d" ".\n\n", line_num, k, actual [k], expected [k]) ;
963 			exit (1) ;
964 			} ;
965 
966 	return ;
967 } /* compare_short_or_die */
968 void
compare_int_or_die(const int * expected,const int * actual,unsigned count,int line_num)969 compare_int_or_die (const int *expected, const int *actual, unsigned count, int line_num)
970 {
971 	unsigned k ;
972 
973 	for (k = 0 ; k < count ; k++)
974 		if (expected [k] != actual [k])
975 		{	printf ("\n\nLine %d : Error at index %d, got " "% d" ", should be " "% d" ".\n\n", line_num, k, actual [k], expected [k]) ;
976 			exit (1) ;
977 			} ;
978 
979 	return ;
980 } /* compare_int_or_die */
981 void
compare_float_or_die(const float * expected,const float * actual,unsigned count,int line_num)982 compare_float_or_die (const float *expected, const float *actual, unsigned count, int line_num)
983 {
984 	unsigned k ;
985 
986 	for (k = 0 ; k < count ; k++)
987 		if (expected [k] != actual [k])
988 		{	printf ("\n\nLine %d : Error at index %d, got " "% g" ", should be " "% g" ".\n\n", line_num, k, actual [k], expected [k]) ;
989 			exit (1) ;
990 			} ;
991 
992 	return ;
993 } /* compare_float_or_die */
994 void
compare_double_or_die(const double * expected,const double * actual,unsigned count,int line_num)995 compare_double_or_die (const double *expected, const double *actual, unsigned count, int line_num)
996 {
997 	unsigned k ;
998 
999 	for (k = 0 ; k < count ; k++)
1000 		if (expected [k] != actual [k])
1001 		{	printf ("\n\nLine %d : Error at index %d, got " "% g" ", should be " "% g" ".\n\n", line_num, k, actual [k], expected [k]) ;
1002 			exit (1) ;
1003 			} ;
1004 
1005 	return ;
1006 } /* compare_double_or_die */
1007 
1008 
1009 
1010 void
delete_file(int format,const char * filename)1011 delete_file (int format, const char *filename)
1012 {	char rsrc_name [512], *fname ;
1013 
1014 	unlink (filename) ;
1015 
1016 	if ((format & SF_FORMAT_TYPEMASK) != SF_FORMAT_SD2)
1017 		return ;
1018 
1019 	/*
1020 	** Now try for a resource fork stored as a separate file.
1021 	** Grab the un-adulterated filename again.
1022 	*/
1023 	snprintf (rsrc_name, sizeof (rsrc_name), "%s", filename) ;
1024 
1025 	if ((fname = strrchr (rsrc_name, '/')) != NULL)
1026 		fname ++ ;
1027 	else if ((fname = strrchr (rsrc_name, '\\')) != NULL)
1028 		fname ++ ;
1029 	else
1030 		fname = rsrc_name ;
1031 
1032 	memmove (fname + 2, fname, strlen (fname) + 1) ;
1033 	fname [0] = '.' ;
1034 	fname [1] = '_' ;
1035 
1036 	unlink (rsrc_name) ;
1037 } /* delete_file */
1038 
1039 int
truncate_file_to_zero(const char * fname)1040 truncate_file_to_zero (const char * fname)
1041 {	FILE * file ;
1042 
1043 	if ((file = fopen (fname, "w")) == NULL)
1044 		return errno ;
1045 	fclose (file) ;
1046 
1047 	return 0 ;
1048 } /* truncate_file_to_zero */
1049 
1050 static int allowed_open_files = -1 ;
1051 
1052 void
count_open_files(void)1053 count_open_files (void)
1054 {
1055 #if OS_IS_WIN32
1056 	return ;
1057 #else
1058 	int k, count = 0 ;
1059 	struct stat statbuf ;
1060 
1061 	if (allowed_open_files > 0)
1062 		return ;
1063 
1064 	for (k = 0 ; k < 1024 ; k++)
1065 		if (fstat (k, &statbuf) == 0)
1066 			count ++ ;
1067 
1068 	allowed_open_files = count ;
1069 #endif
1070 } /* count_open_files */
1071 
1072 void
increment_open_file_count(void)1073 increment_open_file_count (void)
1074 {	allowed_open_files ++ ;
1075 } /* increment_open_file_count */
1076 
1077 void
check_open_file_count_or_die(int lineno)1078 check_open_file_count_or_die (int lineno)
1079 {
1080 #if OS_IS_WIN32
1081 	(void) lineno ;
1082 	return ;
1083 #else
1084 	int k, count = 0 ;
1085 	struct stat statbuf ;
1086 
1087 	if (allowed_open_files < 0)
1088 		count_open_files () ;
1089 
1090 	for (k = 0 ; k < 1024 ; k++)
1091 		if (fstat (k, &statbuf) == 0)
1092 			count ++ ;
1093 
1094 	if (count > allowed_open_files)
1095 	{	printf ("\nLine %d : number of open files (%d) > allowed (%d).\n\n", lineno, count, allowed_open_files) ;
1096 		exit (1) ;
1097 		} ;
1098 #endif
1099 } /* check_open_file_count_or_die */
1100 
1101 void
write_mono_file(const char * filename,int format,int srate,float * output,int len)1102 write_mono_file (const char * filename, int format, int srate, float * output, int len)
1103 {	SNDFILE * file ;
1104 	SF_INFO sfinfo ;
1105 
1106 	memset (&sfinfo, 0, sizeof (sfinfo)) ;
1107 
1108 	sfinfo.samplerate = srate ;
1109 	sfinfo.channels = 1 ;
1110 	sfinfo.format = format ;
1111 
1112 	if ((file = sf_open (filename, SFM_WRITE, &sfinfo)) == NULL)
1113 	{	printf ("sf_open (%s) : %s\n", filename, sf_strerror (NULL)) ;
1114 		exit (1) ;
1115 		} ;
1116 
1117 	sf_write_float (file, output, len) ;
1118 
1119 	sf_close (file) ;
1120 } /* write_mono_file */
1121 
1122 void
gen_lowpass_signal_float(float * data,int len)1123 gen_lowpass_signal_float (float *data, int len)
1124 {	int64_t value = 0x1243456 ;
1125 	double sample, last_val = 0.0 ;
1126 	int k ;
1127 
1128 	for (k = 0 ; k < len ; k++)
1129 	{	/* Not a crypto quality RNG. */
1130 		value = (11117 * value + 211231) & 0xffffffff ;
1131 		value = (11117 * value + 211231) & 0xffffffff ;
1132 		value = (11117 * value + 211231) & 0xffffffff ;
1133 
1134 		sample = value / (0x7fffffff * 1.000001) ;
1135 		sample = 0.2 * sample - 0.9 * last_val ;
1136 
1137 		last_val = sample ;
1138 
1139 		data [k] = 0.5 * (sample + sin (2.0 * k * M_PI * 1.0 / 32.0)) ;
1140 		} ;
1141 
1142 } /* gen_lowpass_signal_float */
1143 
1144 
1145 /*
1146 **	Windows is fucked.
1147 **	If a file is opened R/W and data is written to it, then fstat will return
1148 **	the correct file length, but stat will return zero.
1149 */
1150 
1151 sf_count_t
file_length(const char * fname)1152 file_length (const char * fname)
1153 {	struct stat data ;
1154 
1155 	if (stat (fname, &data) != 0)
1156 		return 0 ;
1157 
1158 	return (sf_count_t) data.st_size ;
1159 } /* file_length */
1160 
1161 sf_count_t
file_length_fd(int fd)1162 file_length_fd (int fd)
1163 {	struct stat data ;
1164 
1165 	memset (&data, 0, sizeof (data)) ;
1166 	if (fstat (fd, &data) != 0)
1167 		return 0 ;
1168 
1169 	return (sf_count_t) data.st_size ;
1170 } /* file_length_fd */
1171 
1172 
1173 
1174 
1175