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