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