utils.tpl 24 KB

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