Imported Upstream version 1.0.26
[platform/upstream/libsndfile.git] / tests / command_test.c
1 /*
2 ** Copyright (C) 2001-2014 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 #include "sfconfig.h"
20
21 #include <stdio.h>
22 #include <stdlib.h>
23 #include <stdint.h>
24 #include <inttypes.h>
25 #include <string.h>
26 #include <time.h>
27
28 #if HAVE_UNISTD_H
29 #include <unistd.h>
30 #endif
31
32 #include <math.h>
33
34 #include <sndfile.h>
35
36 #include "utils.h"
37
38 #define BUFFER_LEN              (1 << 10)
39 #define LOG_BUFFER_SIZE 1024
40
41 static  void    float_norm_test                 (const char *filename) ;
42 static  void    double_norm_test                (const char *filename) ;
43 static  void    format_tests                    (void) ;
44 static  void    calc_peak_test                  (int filetype, const char *filename, int channels) ;
45 static  void    truncate_test                   (const char *filename, int filetype) ;
46 static  void    instrument_test                 (const char *filename, int filetype) ;
47 static  void    channel_map_test                (const char *filename, int filetype) ;
48 static  void    current_sf_info_test    (const char *filename) ;
49 static  void    raw_needs_endswap_test  (const char *filename, int filetype) ;
50
51 static  void    broadcast_test                  (const char *filename, int filetype) ;
52 static  void    broadcast_rdwr_test             (const char *filename, int filetype) ;
53 static  void    broadcast_coding_history_test   (const char *filename) ;
54 static  void    broadcast_coding_history_size   (const char *filename) ;
55
56 /* Cart Chunk tests */
57 static void     cart_test                       (const char *filename, int filetype) ;
58 static void     cart_rdwr_test                  (const char *filename, int filetype) ;
59
60 /* Force the start of this buffer to be double aligned. Sparc-solaris will
61 ** choke if its not.
62 */
63
64 static  int             int_data        [BUFFER_LEN] ;
65 static  float   float_data      [BUFFER_LEN] ;
66 static  double  double_data     [BUFFER_LEN] ;
67
68 int
69 main (int argc, char *argv [])
70 {       int             do_all = 0 ;
71         int             test_count = 0 ;
72
73         if (argc != 2)
74         {       printf ("Usage : %s <test>\n", argv [0]) ;
75                 printf ("    Where <test> is one of the following:\n") ;
76                 printf ("           ver     - test sf_command (SFC_GETLIB_VERSION)\n") ;
77                 printf ("           norm    - test floating point normalisation\n") ;
78                 printf ("           format  - test format string commands\n") ;
79                 printf ("           peak    - test peak calculation\n") ;
80                 printf ("           trunc   - test file truncation\n") ;
81                 printf ("           inst    - test set/get of SF_INSTRUMENT.\n") ;
82                 printf ("           chanmap - test set/get of channel map data..\n") ;
83                 printf ("           bext    - test set/get of SF_BROADCAST_INFO.\n") ;
84                 printf ("           bextch  - test set/get of SF_BROADCAST_INFO coding_history.\n") ;
85                 printf ("           cart    - test set/get of SF_CART_INFO.\n") ;
86                 printf ("           rawend  - test SFC_RAW_NEEDS_ENDSWAP.\n") ;
87                 printf ("           all     - perform all tests\n") ;
88                 exit (1) ;
89                 } ;
90
91         do_all = ! strcmp (argv [1], "all") ;
92
93         if (do_all || strcmp (argv [1], "ver") == 0)
94         {       char buffer [128] ;
95
96                 print_test_name ("version_test", "(none)") ;
97                 buffer [0] = 0 ;
98                 sf_command (NULL, SFC_GET_LIB_VERSION, buffer, sizeof (buffer)) ;
99                 if (strlen (buffer) < 1)
100                 {       printf ("Line %d: could not retrieve lib version.\n", __LINE__) ;
101                         exit (1) ;
102                         } ;
103                 puts ("ok") ;
104                 test_count ++ ;
105                 } ;
106
107         if (do_all || strcmp (argv [1], "norm") == 0)
108         {       /*      Preliminary float/double normalisation tests. More testing
109                 **      is done in the program 'floating_point_test'.
110                 */
111                 float_norm_test         ("float.wav") ;
112                 double_norm_test        ("double.wav") ;
113                 test_count ++ ;
114                 } ;
115
116         if (do_all || strcmp (argv [1], "peak") == 0)
117         {       calc_peak_test (SF_ENDIAN_BIG           | SF_FORMAT_RAW, "be-peak.raw", 1) ;
118                 calc_peak_test (SF_ENDIAN_LITTLE        | SF_FORMAT_RAW, "le-peak.raw", 1) ;
119                 calc_peak_test (SF_ENDIAN_BIG           | SF_FORMAT_RAW, "be-peak.raw", 7) ;
120                 calc_peak_test (SF_ENDIAN_LITTLE        | SF_FORMAT_RAW, "le-peak.raw", 7) ;
121                 test_count ++ ;
122                 } ;
123
124         if (do_all || ! strcmp (argv [1], "format"))
125         {       format_tests () ;
126                 test_count ++ ;
127                 } ;
128
129         if (do_all || strcmp (argv [1], "trunc") == 0)
130         {       truncate_test ("truncate.raw", SF_FORMAT_RAW | SF_FORMAT_PCM_32) ;
131                 truncate_test ("truncate.au" , SF_FORMAT_AU | SF_FORMAT_PCM_16) ;
132                 test_count ++ ;
133                 } ;
134
135         if (do_all || strcmp (argv [1], "inst") == 0)
136         {       instrument_test ("instrument.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_16) ;
137                 instrument_test ("instrument.aiff" , SF_FORMAT_AIFF | SF_FORMAT_PCM_24) ;
138                 /*-instrument_test ("instrument.xi", SF_FORMAT_XI | SF_FORMAT_DPCM_16) ;-*/
139                 test_count ++ ;
140                 } ;
141
142         if (do_all || strcmp (argv [1], "current_sf_info") == 0)
143         {       current_sf_info_test ("current.wav") ;
144                 test_count ++ ;
145                 } ;
146
147         if (do_all || strcmp (argv [1], "bext") == 0)
148         {       broadcast_test ("broadcast.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_16) ;
149                 broadcast_rdwr_test     ("broadcast.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_16) ;
150
151                 broadcast_test ("broadcast.wavex", SF_FORMAT_WAVEX | SF_FORMAT_PCM_16) ;
152                 broadcast_rdwr_test     ("broadcast.wavex", SF_FORMAT_WAVEX | SF_FORMAT_PCM_16) ;
153
154                 broadcast_test ("broadcast.rf64", SF_FORMAT_RF64 | SF_FORMAT_PCM_16) ;
155                 broadcast_rdwr_test     ("broadcast.rf64", SF_FORMAT_RF64 | SF_FORMAT_PCM_16) ;
156                 test_count ++ ;
157                 } ;
158
159         if (do_all || strcmp (argv [1], "cart") == 0)
160         {       cart_test ("cart.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_16) ;
161                 cart_rdwr_test ("cart.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_16) ;
162                 cart_test ("cart.rf64", SF_FORMAT_RF64 | SF_FORMAT_PCM_16) ;
163                 cart_rdwr_test ("cart.rf64", SF_FORMAT_RF64 | SF_FORMAT_PCM_16) ;
164                 test_count ++ ;
165                 } ;
166
167         if (do_all || strcmp (argv [1], "bextch") == 0)
168         {       broadcast_coding_history_test ("coding_history.wav") ;
169                 broadcast_coding_history_size ("coding_hist_size.wav") ;
170                 test_count ++ ;
171                 } ;
172
173         if (do_all || strcmp (argv [1], "chanmap") == 0)
174         {       channel_map_test ("chanmap.wavex", SF_FORMAT_WAVEX | SF_FORMAT_PCM_16) ;
175                 channel_map_test ("chanmap.rf64", SF_FORMAT_RF64 | SF_FORMAT_PCM_16) ;
176                 channel_map_test ("chanmap.aifc" , SF_FORMAT_AIFF | SF_FORMAT_PCM_16) ;
177                 channel_map_test ("chanmap.caf" , SF_FORMAT_CAF | SF_FORMAT_PCM_16) ;
178                 test_count ++ ;
179                 } ;
180
181         if (do_all || strcmp (argv [1], "rawend") == 0)
182         {       raw_needs_endswap_test ("raw_end.wav", SF_FORMAT_WAV) ;
183                 raw_needs_endswap_test ("raw_end.wavex", SF_FORMAT_WAVEX) ;
184                 raw_needs_endswap_test ("raw_end.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV) ;
185                 raw_needs_endswap_test ("raw_end.aiff", SF_FORMAT_AIFF) ;
186                 raw_needs_endswap_test ("raw_end.aiff_le", SF_ENDIAN_LITTLE | SF_FORMAT_AIFF) ;
187                 test_count ++ ;
188                 } ;
189
190         if (test_count == 0)
191         {       printf ("Mono : ************************************\n") ;
192                 printf ("Mono : *  No '%s' test defined.\n", argv [1]) ;
193                 printf ("Mono : ************************************\n") ;
194                 return 1 ;
195                 } ;
196
197         return 0 ;
198 } /* main */
199
200 /*============================================================================================
201 **      Here are the test functions.
202 */
203
204 static void
205 float_norm_test (const char *filename)
206 {       SNDFILE                 *file ;
207         SF_INFO                 sfinfo ;
208         unsigned int    k ;
209
210         print_test_name ("float_norm_test", filename) ;
211
212         sfinfo.samplerate       = 44100 ;
213         sfinfo.format           = (SF_FORMAT_RAW | SF_FORMAT_PCM_16) ;
214         sfinfo.channels         = 1 ;
215         sfinfo.frames           = BUFFER_LEN ;
216
217         /* Create float_data with all values being less than 1.0. */
218         for (k = 0 ; k < BUFFER_LEN / 2 ; k++)
219                 float_data [k] = (k + 5) / (2.0 * BUFFER_LEN) ;
220         for (k = BUFFER_LEN / 2 ; k < BUFFER_LEN ; k++)
221                 float_data [k] = (k + 5) ;
222
223         if (! (file = sf_open (filename, SFM_WRITE, &sfinfo)))
224         {       printf ("Line %d: sf_open_write failed with error : ", __LINE__) ;
225                 fflush (stdout) ;
226                 puts (sf_strerror (NULL)) ;
227                 exit (1) ;
228                 } ;
229
230         /* Normalisation is on by default so no need to do anything here. */
231
232         if ((k = sf_write_float (file, float_data, BUFFER_LEN / 2)) != BUFFER_LEN / 2)
233         {       printf ("Line %d: sf_write_float failed with short write (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ;
234                 exit (1) ;
235                 } ;
236
237         /* Turn normalisation off. */
238         sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
239
240         if ((k = sf_write_float (file, float_data + BUFFER_LEN / 2, BUFFER_LEN / 2)) != BUFFER_LEN / 2)
241         {       printf ("Line %d: sf_write_float failed with short write (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ;
242                 exit (1) ;
243                 } ;
244
245         sf_close (file) ;
246
247         /* sfinfo struct should still contain correct data. */
248         if (! (file = sf_open (filename, SFM_READ, &sfinfo)))
249         {       printf ("Line %d: sf_open_read failed with error : ", __LINE__) ;
250                 fflush (stdout) ;
251                 puts (sf_strerror (NULL)) ;
252                 exit (1) ;
253                 } ;
254
255         if (sfinfo.format != (SF_FORMAT_RAW | SF_FORMAT_PCM_16))
256         {       printf ("Line %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, (SF_FORMAT_RAW | SF_FORMAT_PCM_16), sfinfo.format) ;
257                 exit (1) ;
258                 } ;
259
260         if (sfinfo.frames != BUFFER_LEN)
261         {       printf ("\n\nLine %d: Incorrect number of.frames in file. (%d => %" PRId64 ")\n", __LINE__, BUFFER_LEN, sfinfo.frames) ;
262                 exit (1) ;
263                 } ;
264
265         if (sfinfo.channels != 1)
266         {       printf ("Line %d: Incorrect number of channels in file.\n", __LINE__) ;
267                 exit (1) ;
268                 } ;
269
270         /* Read float_data and check that it is normalised (ie default). */
271         if ((k = sf_read_float (file, float_data, BUFFER_LEN)) != BUFFER_LEN)
272         {       printf ("\n\nLine %d: sf_read_float failed with short read (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ;
273                 exit (1) ;
274                 } ;
275
276         for (k = 0 ; k < BUFFER_LEN ; k++)
277                 if (float_data [k] >= 1.0)
278                 {       printf ("\n\nLine %d: float_data [%d] == %f which is greater than 1.0\n", __LINE__, k, float_data [k]) ;
279                         exit (1) ;
280                         } ;
281
282         /* Seek to start of file, turn normalisation off, read float_data and check again. */
283         sf_seek (file, 0, SEEK_SET) ;
284         sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
285
286         if ((k = sf_read_float (file, float_data, BUFFER_LEN)) != BUFFER_LEN)
287         {       printf ("\n\nLine %d: sf_read_float failed with short read (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ;
288                 exit (1) ;
289                 } ;
290
291         for (k = 0 ; k < BUFFER_LEN ; k++)
292                 if (float_data [k] < 1.0)
293                 {       printf ("\n\nLine %d: float_data [%d] == %f which is less than 1.0\n", __LINE__, k, float_data [k]) ;
294                         exit (1) ;
295                         } ;
296
297         /* Seek to start of file, turn normalisation on, read float_data and do final check. */
298         sf_seek (file, 0, SEEK_SET) ;
299         sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_TRUE) ;
300
301         if ((k = sf_read_float (file, float_data, BUFFER_LEN)) != BUFFER_LEN)
302         {       printf ("\n\nLine %d: sf_read_float failed with short read (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ;
303                 exit (1) ;
304                 } ;
305
306         for (k = 0 ; k < BUFFER_LEN ; k++)
307                 if (float_data [k] > 1.0)
308                 {       printf ("\n\nLine %d: float_data [%d] == %f which is greater than 1.0\n", __LINE__, k, float_data [k]) ;
309                         exit (1) ;
310                         } ;
311
312
313         sf_close (file) ;
314
315         unlink (filename) ;
316
317         printf ("ok\n") ;
318 } /* float_norm_test */
319
320 static void
321 double_norm_test (const char *filename)
322 {       SNDFILE                 *file ;
323         SF_INFO                 sfinfo ;
324         unsigned int    k ;
325
326         print_test_name ("double_norm_test", filename) ;
327
328         sfinfo.samplerate       = 44100 ;
329         sfinfo.format           = (SF_FORMAT_RAW | SF_FORMAT_PCM_16) ;
330         sfinfo.channels         = 1 ;
331         sfinfo.frames           = BUFFER_LEN ;
332
333         /* Create double_data with all values being less than 1.0. */
334         for (k = 0 ; k < BUFFER_LEN / 2 ; k++)
335                 double_data [k] = (k + 5) / (2.0 * BUFFER_LEN) ;
336         for (k = BUFFER_LEN / 2 ; k < BUFFER_LEN ; k++)
337                 double_data [k] = (k + 5) ;
338
339         if (! (file = sf_open (filename, SFM_WRITE, &sfinfo)))
340         {       printf ("Line %d: sf_open_write failed with error : ", __LINE__) ;
341                 fflush (stdout) ;
342                 puts (sf_strerror (NULL)) ;
343                 exit (1) ;
344                 } ;
345
346         /* Normailsation is on by default so no need to do anything here. */
347         /*-sf_command (file, "set-norm-double", "true", 0) ;-*/
348
349         if ((k = sf_write_double (file, double_data, BUFFER_LEN / 2)) != BUFFER_LEN / 2)
350         {       printf ("Line %d: sf_write_double failed with short write (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ;
351                 exit (1) ;
352                 } ;
353
354         /* Turn normalisation off. */
355         sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
356
357         if ((k = sf_write_double (file, double_data + BUFFER_LEN / 2, BUFFER_LEN / 2)) != BUFFER_LEN / 2)
358         {       printf ("Line %d: sf_write_double failed with short write (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ;
359                 exit (1) ;
360                 } ;
361
362         sf_close (file) ;
363
364         if (! (file = sf_open (filename, SFM_READ, &sfinfo)))
365         {       printf ("Line %d: sf_open_read failed with error : ", __LINE__) ;
366                 fflush (stdout) ;
367                 puts (sf_strerror (NULL)) ;
368                 exit (1) ;
369                 } ;
370
371         if (sfinfo.format != (SF_FORMAT_RAW | SF_FORMAT_PCM_16))
372         {       printf ("Line %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, (SF_FORMAT_RAW | SF_FORMAT_PCM_16), sfinfo.format) ;
373                 exit (1) ;
374                 } ;
375
376         if (sfinfo.frames != BUFFER_LEN)
377         {       printf ("\n\nLine %d: Incorrect number of.frames in file. (%d => %" PRId64 ")\n", __LINE__, BUFFER_LEN, sfinfo.frames) ;
378                 exit (1) ;
379                 } ;
380
381         if (sfinfo.channels != 1)
382         {       printf ("Line %d: Incorrect number of channels in file.\n", __LINE__) ;
383                 exit (1) ;
384                 } ;
385
386         /* Read double_data and check that it is normalised (ie default). */
387         if ((k = sf_read_double (file, double_data, BUFFER_LEN)) != BUFFER_LEN)
388         {       printf ("\n\nLine %d: sf_read_double failed with short read (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ;
389                 exit (1) ;
390                 } ;
391
392         for (k = 0 ; k < BUFFER_LEN ; k++)
393                 if (double_data [k] >= 1.0)
394                 {       printf ("\n\nLine %d: double_data [%d] == %f which is greater than 1.0\n", __LINE__, k, double_data [k]) ;
395                         exit (1) ;
396                         } ;
397
398         /* Seek to start of file, turn normalisation off, read double_data and check again. */
399         sf_seek (file, 0, SEEK_SET) ;
400         sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
401
402         if ((k = sf_read_double (file, double_data, BUFFER_LEN)) != BUFFER_LEN)
403         {       printf ("\n\nLine %d: sf_read_double failed with short read (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ;
404                 exit (1) ;
405                 } ;
406
407         for (k = 0 ; k < BUFFER_LEN ; k++)
408                 if (double_data [k] < 1.0)
409                 {       printf ("\n\nLine %d: double_data [%d] == %f which is less than 1.0\n", __LINE__, k, double_data [k]) ;
410                         exit (1) ;
411                         } ;
412
413         /* Seek to start of file, turn normalisation on, read double_data and do final check. */
414         sf_seek (file, 0, SEEK_SET) ;
415         sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_TRUE) ;
416
417         if ((k = sf_read_double (file, double_data, BUFFER_LEN)) != BUFFER_LEN)
418         {       printf ("\n\nLine %d: sf_read_double failed with short read (%d ->%d)\n", __LINE__, BUFFER_LEN, k) ;
419                 exit (1) ;
420                 } ;
421
422         for (k = 0 ; k < BUFFER_LEN ; k++)
423                 if (double_data [k] > 1.0)
424                 {       printf ("\n\nLine %d: double_data [%d] == %f which is greater than 1.0\n", __LINE__, k, double_data [k]) ;
425                         exit (1) ;
426                         } ;
427
428
429         sf_close (file) ;
430
431         unlink (filename) ;
432
433         printf ("ok\n") ;
434 } /* double_norm_test */
435
436 static  void
437 format_tests    (void)
438 {       SF_FORMAT_INFO format_info ;
439         SF_INFO         sfinfo ;
440         const char      *last_name ;
441         int             k, count ;
442
443         print_test_name ("format_tests", "(null)") ;
444
445         /* Clear out SF_INFO struct and set channels > 0. */
446         memset (&sfinfo, 0, sizeof (sfinfo)) ;
447         sfinfo.channels = 1 ;
448
449         /* First test simple formats. */
450
451         sf_command (NULL, SFC_GET_SIMPLE_FORMAT_COUNT, &count, sizeof (int)) ;
452
453         if (count < 0 || count > 30)
454         {       printf ("Line %d: Weird count.\n", __LINE__) ;
455                 exit (1) ;
456                 } ;
457
458         format_info.format = 0 ;
459         sf_command (NULL, SFC_GET_SIMPLE_FORMAT, &format_info, sizeof (format_info)) ;
460
461         last_name = format_info.name ;
462         for (k = 1 ; k < count ; k ++)
463         {       format_info.format = k ;
464                 sf_command (NULL, SFC_GET_SIMPLE_FORMAT, &format_info, sizeof (format_info)) ;
465                 if (strcmp (last_name, format_info.name) >= 0)
466                 {       printf ("\n\nLine %d: format names out of sequence `%s' < `%s'.\n", __LINE__, last_name, format_info.name) ;
467                         exit (1) ;
468                         } ;
469                 sfinfo.format = format_info.format ;
470
471                 if (! sf_format_check (&sfinfo))
472                 {       printf ("\n\nLine %d: sf_format_check failed.\n", __LINE__) ;
473                         printf ("        Name : %s\n", format_info.name) ;
474                         printf ("        Format      : 0x%X\n", sfinfo.format) ;
475                         printf ("        Channels    : 0x%X\n", sfinfo.channels) ;
476                         printf ("        Sample Rate : 0x%X\n", sfinfo.samplerate) ;
477                         exit (1) ;
478                         } ;
479                 last_name = format_info.name ;
480                 } ;
481         format_info.format = 666 ;
482         sf_command (NULL, SFC_GET_SIMPLE_FORMAT, &format_info, sizeof (format_info)) ;
483
484         /* Now test major formats. */
485         sf_command (NULL, SFC_GET_FORMAT_MAJOR_COUNT, &count, sizeof (int)) ;
486
487         if (count < 0 || count > 30)
488         {       printf ("Line %d: Weird count.\n", __LINE__) ;
489                 exit (1) ;
490                 } ;
491
492         format_info.format = 0 ;
493         sf_command (NULL, SFC_GET_FORMAT_MAJOR, &format_info, sizeof (format_info)) ;
494
495         last_name = format_info.name ;
496         for (k = 1 ; k < count ; k ++)
497         {       format_info.format = k ;
498                 sf_command (NULL, SFC_GET_FORMAT_MAJOR, &format_info, sizeof (format_info)) ;
499                 if (strcmp (last_name, format_info.name) >= 0)
500                 {       printf ("\n\nLine %d: format names out of sequence (%d) `%s' < `%s'.\n", __LINE__, k, last_name, format_info.name) ;
501                         exit (1) ;
502                         } ;
503
504                 last_name = format_info.name ;
505                 } ;
506         format_info.format = 666 ;
507         sf_command (NULL, SFC_GET_FORMAT_MAJOR, &format_info, sizeof (format_info)) ;
508
509         /* Now test subtype formats. */
510         sf_command (NULL, SFC_GET_FORMAT_SUBTYPE_COUNT, &count, sizeof (int)) ;
511
512         if (count < 0 || count > 30)
513         {       printf ("Line %d: Weird count.\n", __LINE__) ;
514                 exit (1) ;
515                 } ;
516
517         format_info.format = 0 ;
518         sf_command (NULL, SFC_GET_FORMAT_SUBTYPE, &format_info, sizeof (format_info)) ;
519
520         last_name = format_info.name ;
521         for (k = 1 ; k < count ; k ++)
522         {       format_info.format = k ;
523                 sf_command (NULL, SFC_GET_FORMAT_SUBTYPE, &format_info, sizeof (format_info)) ;
524                 } ;
525         format_info.format = 666 ;
526         sf_command (NULL, SFC_GET_FORMAT_SUBTYPE, &format_info, sizeof (format_info)) ;
527
528
529         printf ("ok\n") ;
530 } /* format_tests */
531
532 static  void
533 calc_peak_test (int filetype, const char *filename, int channels)
534 {       SNDFILE         *file ;
535         SF_INFO         sfinfo ;
536         char            label [128] ;
537         int                     k, format ;
538         sf_count_t      buffer_len, frame_count ;
539         double          peak ;
540
541         snprintf (label, sizeof (label), "calc_peak_test (%d channels)", channels) ;
542         print_test_name (label, filename) ;
543
544         format = filetype | SF_FORMAT_PCM_16 ;
545
546         buffer_len = BUFFER_LEN - (BUFFER_LEN % channels) ;
547         frame_count = buffer_len / channels ;
548
549         sfinfo.samplerate       = 44100 ;
550         sfinfo.format           = format ;
551         sfinfo.channels         = channels ;
552         sfinfo.frames           = frame_count ;
553
554         /* Create double_data with max value of 0.5. */
555         for (k = 0 ; k < buffer_len ; k++)
556                 double_data [k] = (k + 1) / (2.0 * buffer_len) ;
557
558         file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
559
560         test_writef_double_or_die (file, 0, double_data, frame_count, __LINE__) ;
561
562         sf_close (file) ;
563
564         file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
565
566         if (sfinfo.format != format)
567         {       printf ("Line %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, format, sfinfo.format) ;
568                 exit (1) ;
569                 } ;
570
571         if (sfinfo.frames != frame_count)
572         {       printf ("\n\nLine %d: Incorrect number of frames in file. (%" PRId64 " => %" PRId64 ")\n", __LINE__, frame_count, sfinfo.frames) ;
573                 exit (1) ;
574                 } ;
575
576         if (sfinfo.channels != channels)
577         {       printf ("Line %d: Incorrect number of channels in file.\n", __LINE__) ;
578                 exit (1) ;
579                 } ;
580
581         sf_command (file, SFC_CALC_SIGNAL_MAX, &peak, sizeof (peak)) ;
582         if (fabs (peak - (1 << 14)) > 1.0)
583         {       printf ("Line %d : Peak value should be %d (is %f).\n", __LINE__, (1 << 14), peak) ;
584                 exit (1) ;
585                 } ;
586
587         sf_command (file, SFC_CALC_NORM_SIGNAL_MAX, &peak, sizeof (peak)) ;
588         if (fabs (peak - 0.5) > 4e-5)
589         {       printf ("Line %d : Peak value should be %f (is %f).\n", __LINE__, 0.5, peak) ;
590                 exit (1) ;
591                 } ;
592
593         sf_close (file) ;
594
595         format = (filetype | SF_FORMAT_FLOAT) ;
596         sfinfo.samplerate       = 44100 ;
597         sfinfo.format           = format ;
598         sfinfo.channels         = channels ;
599         sfinfo.frames           = frame_count ;
600
601         /* Create double_data with max value of 0.5. */
602         for (k = 0 ; k < buffer_len ; k++)
603                 double_data [k] = (k + 1) / (2.0 * buffer_len) ;
604
605         file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
606
607         test_writef_double_or_die (file, 0, double_data, frame_count, __LINE__) ;
608
609         sf_close (file) ;
610
611         file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
612
613         if (sfinfo.format != format)
614         {       printf ("Line %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, format, sfinfo.format) ;
615                 exit (1) ;
616                 } ;
617
618         if (sfinfo.frames != frame_count)
619         {       printf ("\n\nLine %d: Incorrect number of.frames in file. (%" PRId64 " => %" PRId64 ")\n", __LINE__, frame_count, sfinfo.frames) ;
620                 exit (1) ;
621                 } ;
622
623         if (sfinfo.channels != channels)
624         {       printf ("Line %d: Incorrect number of channels in file.\n", __LINE__) ;
625                 exit (1) ;
626                 } ;
627
628         sf_command (file, SFC_CALC_SIGNAL_MAX, &peak, sizeof (peak)) ;
629         if (fabs (peak - 0.5) > 1e-5)
630         {       printf ("Line %d : Peak value should be %f (is %f).\n", __LINE__, 0.5, peak) ;
631                 exit (1) ;
632                 } ;
633
634         sf_command (file, SFC_CALC_NORM_SIGNAL_MAX, &peak, sizeof (peak)) ;
635         if (fabs (peak - 0.5) > 1e-5)
636         {       printf ("Line %d : Peak value should be %f (is %f).\n", __LINE__, 0.5, peak) ;
637                 exit (1) ;
638                 } ;
639
640         sf_close (file) ;
641
642         unlink (filename) ;
643
644         printf ("ok\n") ;
645 } /* calc_peak_test */
646
647 static void
648 truncate_test (const char *filename, int filetype)
649 {       SNDFILE         *file ;
650         SF_INFO         sfinfo ;
651         sf_count_t      len ;
652
653         print_test_name ("truncate_test", filename) ;
654
655         sfinfo.samplerate       = 11025 ;
656         sfinfo.format           = filetype ;
657         sfinfo.channels         = 2 ;
658
659         file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_TRUE, __LINE__) ;
660
661         test_write_int_or_die (file, 0, int_data, BUFFER_LEN, __LINE__) ;
662
663         len = 100 ;
664         if (sf_command (file, SFC_FILE_TRUNCATE, &len, sizeof (len)))
665         {       printf ("Line %d: sf_command (SFC_FILE_TRUNCATE) returned error.\n", __LINE__) ;
666                 exit (1) ;
667                 } ;
668
669         test_seek_or_die (file, 0, SEEK_CUR, len, 2, __LINE__) ;
670         test_seek_or_die (file, 0, SEEK_END, len, 2, __LINE__) ;
671
672         sf_close (file) ;
673
674         unlink (filename) ;
675         puts ("ok") ;
676 } /* truncate_test */
677
678 /*------------------------------------------------------------------------------
679 */
680
681 static void
682 instrumet_rw_test (const char *filename)
683 {       SNDFILE *sndfile ;
684         SF_INFO sfinfo ;
685         SF_INSTRUMENT inst ;
686         memset (&sfinfo, 0, sizeof (SF_INFO)) ;
687
688         sndfile = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_FALSE, __LINE__) ;
689
690         if (sf_command (sndfile, SFC_GET_INSTRUMENT, &inst, sizeof (inst)) == SF_TRUE)
691         {       inst.basenote = 22 ;
692
693                 if (sf_command (sndfile, SFC_SET_INSTRUMENT, &inst, sizeof (inst)) == SF_TRUE)
694                         printf ("Sucess: [%s] updated\n", filename) ;
695                 else
696                         printf ("Error: SFC_SET_INSTRUMENT on [%s] [%s]\n", filename, sf_strerror (sndfile)) ;
697                 }
698         else
699                 printf ("Error: SFC_GET_INSTRUMENT on [%s] [%s]\n", filename, sf_strerror (sndfile)) ;
700
701
702         if (sf_command (sndfile, SFC_UPDATE_HEADER_NOW, NULL, 0) != 0)
703                 printf ("Error: SFC_UPDATE_HEADER_NOW on [%s] [%s]\n", filename, sf_strerror (sndfile)) ;
704
705         sf_write_sync (sndfile) ;
706         sf_close (sndfile) ;
707
708         return ;
709 } /* instrumet_rw_test */
710
711 static void
712 instrument_test (const char *filename, int filetype)
713 {       static SF_INSTRUMENT write_inst =
714         {       2,              /* gain */
715                 3,              /* detune */
716                 4,              /* basenote */
717                 5, 6,   /* key low and high */
718                 7, 8,   /* velocity low and high */
719                 2,              /* loop_count */
720                 {       {       801, 2, 3, 0 },
721                         {       801, 3, 4, 0 },
722                 }
723         } ;
724         SF_INSTRUMENT read_inst ;
725         SNDFILE *file ;
726         SF_INFO sfinfo ;
727
728         print_test_name ("instrument_test", filename) ;
729
730         sfinfo.samplerate       = 11025 ;
731         sfinfo.format           = filetype ;
732         sfinfo.channels         = 1 ;
733
734         file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
735         if (sf_command (file, SFC_SET_INSTRUMENT, &write_inst, sizeof (write_inst)) == SF_FALSE)
736         {       printf ("\n\nLine %d : sf_command (SFC_SET_INSTRUMENT) failed.\n\n", __LINE__) ;
737                 exit (1) ;
738                 } ;
739         test_write_double_or_die (file, 0, double_data, BUFFER_LEN, __LINE__) ;
740         sf_close (file) ;
741
742         memset (&read_inst, 0, sizeof (read_inst)) ;
743
744         file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
745         if (sf_command (file, SFC_GET_INSTRUMENT, &read_inst, sizeof (read_inst)) == SF_FALSE)
746         {       printf ("\n\nLine %d : sf_command (SFC_GET_INSTRUMENT) failed.\n\n", __LINE__) ;
747                 exit (1) ;
748                 return ;
749                 } ;
750         check_log_buffer_or_die (file, __LINE__) ;
751         sf_close (file) ;
752
753         if ((filetype & SF_FORMAT_TYPEMASK) == SF_FORMAT_WAV)
754         {       /*
755                 **      For all the fields that WAV doesn't support, modify the
756                 **      write_inst struct to hold the default value that the WAV
757                 **      module should hold.
758                 */
759                 write_inst.detune = 0 ;
760                 write_inst.key_lo = write_inst.velocity_lo = 0 ;
761                 write_inst.key_hi = write_inst.velocity_hi = 127 ;
762                 write_inst.gain = 1 ;
763                 } ;
764
765         if ((filetype & SF_FORMAT_TYPEMASK) == SF_FORMAT_XI)
766         {       /*
767                 **      For all the fields that XI doesn't support, modify the
768                 **      write_inst struct to hold the default value that the XI
769                 **      module should hold.
770                 */
771                 write_inst.basenote = 0 ;
772                 write_inst.detune = 0 ;
773                 write_inst.key_lo = write_inst.velocity_lo = 0 ;
774                 write_inst.key_hi = write_inst.velocity_hi = 127 ;
775                 write_inst.gain = 1 ;
776                 } ;
777
778         if (memcmp (&write_inst, &read_inst, sizeof (write_inst)) != 0)
779         {       printf ("\n\nLine %d : instrument comparison failed.\n\n", __LINE__) ;
780                 printf ("W  Base Note : %u\n"
781                         "   Detune    : %u\n"
782                         "   Low  Note : %u\tHigh Note : %u\n"
783                         "   Low  Vel. : %u\tHigh Vel. : %u\n"
784                         "   Gain      : %d\tCount     : %d\n"
785                         "   mode      : %d\n"
786                         "   start     : %d\tend       : %d\tcount  :%d\n"
787                         "   mode      : %d\n"
788                         "   start     : %d\tend       : %d\tcount  :%d\n\n",
789                         write_inst.basenote,
790                         write_inst.detune,
791                         write_inst.key_lo, write_inst.key_hi,
792                         write_inst.velocity_lo, write_inst.velocity_hi,
793                         write_inst.gain, write_inst.loop_count,
794                         write_inst.loops [0].mode, write_inst.loops [0].start,
795                         write_inst.loops [0].end, write_inst.loops [0].count,
796                         write_inst.loops [1].mode, write_inst.loops [1].start,
797                         write_inst.loops [1].end, write_inst.loops [1].count) ;
798                 printf ("R  Base Note : %u\n"
799                         "   Detune    : %u\n"
800                         "   Low  Note : %u\tHigh Note : %u\n"
801                         "   Low  Vel. : %u\tHigh Vel. : %u\n"
802                         "   Gain      : %d\tCount     : %d\n"
803                         "   mode      : %d\n"
804                         "   start     : %d\tend       : %d\tcount  :%d\n"
805                         "   mode      : %d\n"
806                         "   start     : %d\tend       : %d\tcount  :%d\n\n",
807                         read_inst.basenote,
808                         read_inst.detune,
809                         read_inst.key_lo, read_inst.key_hi,
810                         read_inst.velocity_lo, read_inst.velocity_hi,
811                         read_inst.gain, read_inst.loop_count,
812                         read_inst.loops [0].mode, read_inst.loops [0].start,
813                         read_inst.loops [0].end, read_inst.loops [0].count,
814                         read_inst.loops [1].mode, read_inst.loops [1].start,
815                         read_inst.loops [1].end, read_inst.loops [1].count) ;
816
817                 if ((filetype & SF_FORMAT_TYPEMASK) != SF_FORMAT_XI)
818                         exit (1) ;
819                 } ;
820
821         if (0) instrumet_rw_test (filename) ;
822
823         unlink (filename) ;
824         puts ("ok") ;
825 } /* instrument_test */
826
827 static  void
828 current_sf_info_test    (const char *filename)
829 {       SNDFILE *outfile, *infile ;
830         SF_INFO outinfo, ininfo ;
831
832         print_test_name ("current_sf_info_test", filename) ;
833
834         outinfo.samplerate      = 44100 ;
835         outinfo.format          = (SF_FORMAT_WAV | SF_FORMAT_PCM_16) ;
836         outinfo.channels        = 1 ;
837         outinfo.frames          = 0 ;
838
839         outfile = test_open_file_or_die (filename, SFM_WRITE, &outinfo, SF_TRUE, __LINE__) ;
840         sf_command (outfile, SFC_SET_UPDATE_HEADER_AUTO, NULL, 0) ;
841
842         exit_if_true (outinfo.frames != 0,
843                 "\n\nLine %d : Initial sfinfo.frames is not zero.\n\n", __LINE__
844                 ) ;
845
846         test_write_double_or_die (outfile, 0, double_data, BUFFER_LEN, __LINE__) ;
847         sf_command (outfile, SFC_GET_CURRENT_SF_INFO, &outinfo, sizeof (outinfo)) ;
848
849         exit_if_true (outinfo.frames != BUFFER_LEN,
850                 "\n\nLine %d : Initial sfinfo.frames (%" PRId64 ") should be %d.\n\n", __LINE__,
851                 outinfo.frames, BUFFER_LEN
852                 ) ;
853
854         /* Read file making sure no channel map exists. */
855         memset (&ininfo, 0, sizeof (ininfo)) ;
856         infile = test_open_file_or_die (filename, SFM_READ, &ininfo, SF_TRUE, __LINE__) ;
857
858         test_write_double_or_die (outfile, 0, double_data, BUFFER_LEN, __LINE__) ;
859
860         sf_command (infile, SFC_GET_CURRENT_SF_INFO, &ininfo, sizeof (ininfo)) ;
861
862         exit_if_true (ininfo.frames != BUFFER_LEN,
863                 "\n\nLine %d : Initial sfinfo.frames (%" PRId64 ") should be %d.\n\n", __LINE__,
864                 ininfo.frames, BUFFER_LEN
865                 ) ;
866
867         sf_close (outfile) ;
868         sf_close (infile) ;
869
870         unlink (filename) ;
871         puts ("ok") ;
872 } /* current_sf_info_test */
873
874 static void
875 broadcast_test (const char *filename, int filetype)
876 {       static SF_BROADCAST_INFO bc_write, bc_read ;
877         SNDFILE *file ;
878         SF_INFO sfinfo ;
879         int errors = 0 ;
880
881         print_test_name ("broadcast_test", filename) ;
882
883         sfinfo.samplerate       = 11025 ;
884         sfinfo.format           = filetype ;
885         sfinfo.channels         = 1 ;
886
887         memset (&bc_write, 0, sizeof (bc_write)) ;
888
889         snprintf (bc_write.description, sizeof (bc_write.description), "Test description") ;
890         snprintf (bc_write.originator, sizeof (bc_write.originator), "Test originator") ;
891         snprintf (bc_write.originator_reference, sizeof (bc_write.originator_reference), "%08x-%08x", (unsigned int) time (NULL), (unsigned int) (~ time (NULL))) ;
892         snprintf (bc_write.origination_date, sizeof (bc_write.origination_date), "%d/%02d/%02d", 2006, 3, 30) ;
893         snprintf (bc_write.origination_time, sizeof (bc_write.origination_time), "%02d:%02d:%02d", 20, 27, 0) ;
894         snprintf (bc_write.umid, sizeof (bc_write.umid), "Some umid") ;
895         bc_write.coding_history_size = 0 ;
896
897         file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
898         if (sf_command (file, SFC_SET_BROADCAST_INFO, &bc_write, sizeof (bc_write)) == SF_FALSE)
899         {       printf ("\n\nLine %d : sf_command (SFC_SET_BROADCAST_INFO) failed.\n\n", __LINE__) ;
900                 exit (1) ;
901                 } ;
902         test_write_double_or_die (file, 0, double_data, BUFFER_LEN, __LINE__) ;
903         sf_close (file) ;
904
905         memset (&bc_read, 0, sizeof (bc_read)) ;
906
907         file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
908         if (sf_command (file, SFC_GET_BROADCAST_INFO, &bc_read, sizeof (bc_read)) == SF_FALSE)
909         {       printf ("\n\nLine %d : sf_command (SFC_GET_BROADCAST_INFO) failed.\n\n", __LINE__) ;
910                 exit (1) ;
911                 return ;
912                 } ;
913         check_log_buffer_or_die (file, __LINE__) ;
914         sf_close (file) ;
915
916         if (bc_read.version != 1)
917         {       printf ("\n\nLine %d : Read bad version number %d.\n\n", __LINE__, bc_read.version) ;
918                 exit (1) ;
919                 return ;
920                 } ;
921
922         bc_read.version = bc_write.version = 0 ;
923
924         if (memcmp (bc_write.description, bc_read.description, sizeof (bc_write.description)) != 0)
925         {       printf ("\n\nLine %d : description mismatch :\n\twrite : '%s'\n\tread  : '%s'\n\n", __LINE__, bc_write.description, bc_read.description) ;
926                 errors ++ ;
927                 } ;
928
929         if (memcmp (bc_write.originator, bc_read.originator, sizeof (bc_write.originator)) != 0)
930         {       printf ("\n\nLine %d : originator mismatch :\n\twrite : '%s'\n\tread  : '%s'\n\n", __LINE__, bc_write.originator, bc_read.originator) ;
931                 errors ++ ;
932                 } ;
933
934         if (memcmp (bc_write.originator_reference, bc_read.originator_reference, sizeof (bc_write.originator_reference)) != 0)
935         {       printf ("\n\nLine %d : originator_reference mismatch :\n\twrite : '%s'\n\tread  : '%s'\n\n", __LINE__, bc_write.originator_reference, bc_read.originator_reference) ;
936                 errors ++ ;
937                 } ;
938
939         if (memcmp (bc_write.origination_date, bc_read.origination_date, sizeof (bc_write.origination_date)) != 0)
940         {       printf ("\n\nLine %d : origination_date mismatch :\n\twrite : '%s'\n\tread  : '%s'\n\n", __LINE__, bc_write.origination_date, bc_read.origination_date) ;
941                 errors ++ ;
942                 } ;
943
944         if (memcmp (bc_write.origination_time, bc_read.origination_time, sizeof (bc_write.origination_time)) != 0)
945         {       printf ("\n\nLine %d : origination_time mismatch :\n\twrite : '%s'\n\tread  : '%s'\n\n", __LINE__, bc_write.origination_time, bc_read.origination_time) ;
946                 errors ++ ;
947                 } ;
948
949         if (memcmp (bc_write.umid, bc_read.umid, sizeof (bc_write.umid)) != 0)
950         {       printf ("\n\nLine %d : umid mismatch :\n\twrite : '%s'\n\tread  : '%s'\n\n", __LINE__, bc_write.umid, bc_read.umid) ;
951                 errors ++ ;
952                 } ;
953
954         if (errors)
955                 exit (1) ;
956
957         unlink (filename) ;
958         puts ("ok") ;
959 } /* broadcast_test */
960
961 static  void
962 broadcast_rdwr_test (const char *filename, int filetype)
963 {       SF_BROADCAST_INFO binfo ;
964         SNDFILE *file ;
965         SF_INFO sfinfo ;
966         sf_count_t frames ;
967
968         print_test_name (__func__, filename) ;
969
970         create_short_sndfile (filename, filetype, 2) ;
971
972         memset (&sfinfo, 0, sizeof (sfinfo)) ;
973         memset (&binfo, 0, sizeof (binfo)) ;
974
975         snprintf (binfo.description, sizeof (binfo.description), "Test description") ;
976         snprintf (binfo.originator, sizeof (binfo.originator), "Test originator") ;
977         snprintf (binfo.originator_reference, sizeof (binfo.originator_reference), "%08x-%08x", (unsigned int) time (NULL), (unsigned int) (~ time (NULL))) ;
978         snprintf (binfo.origination_date, sizeof (binfo.origination_date), "%d/%02d/%02d", 2006, 3, 30) ;
979         snprintf (binfo.origination_time, sizeof (binfo.origination_time), "%02d:%02d:%02d", 20, 27, 0) ;
980         snprintf (binfo.umid, sizeof (binfo.umid), "Some umid") ;
981         binfo.coding_history_size = 0 ;
982
983         file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_TRUE, __LINE__) ;
984         frames = sfinfo.frames ;
985         if (sf_command (file, SFC_SET_BROADCAST_INFO, &binfo, sizeof (binfo)) != SF_FALSE)
986         {       printf ("\n\nLine %d : sf_command (SFC_SET_BROADCAST_INFO) should have failed but didn't.\n\n", __LINE__) ;
987                 exit (1) ;
988                 } ;
989         sf_close (file) ;
990
991         file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
992         sf_close (file) ;
993         exit_if_true (frames != sfinfo.frames, "\n\nLine %d : Frame count %" PRId64 " should be %" PRId64 ".\n", __LINE__, sfinfo.frames, frames) ;
994
995         unlink (filename) ;
996         puts ("ok") ;
997 } /* broadcast_rdwr_test */
998
999 static void
1000 check_coding_history_newlines (const char *filename)
1001 {       static SF_BROADCAST_INFO bc_write, bc_read ;
1002         SNDFILE *file ;
1003         SF_INFO sfinfo ;
1004         unsigned k ;
1005
1006         sfinfo.samplerate       = 22050 ;
1007         sfinfo.format           = SF_FORMAT_WAV | SF_FORMAT_PCM_16 ;
1008         sfinfo.channels         = 1 ;
1009
1010         memset (&bc_write, 0, sizeof (bc_write)) ;
1011
1012         snprintf (bc_write.description, sizeof (bc_write.description), "Test description") ;
1013         snprintf (bc_write.originator, sizeof (bc_write.originator), "Test originator") ;
1014         snprintf (bc_write.originator_reference, sizeof (bc_write.originator_reference), "%08x-%08x", (unsigned int) time (NULL), (unsigned int) (~ time (NULL))) ;
1015         snprintf (bc_write.origination_date, sizeof (bc_write.origination_date), "%d/%02d/%02d", 2006, 3, 30) ;
1016         snprintf (bc_write.origination_time, sizeof (bc_write.origination_time), "%02d:%02d:%02d", 20, 27, 0) ;
1017         snprintf (bc_write.umid, sizeof (bc_write.umid), "Some umid") ;
1018         bc_write.coding_history_size = snprintf (bc_write.coding_history, sizeof (bc_write.coding_history), "This has\nUnix\nand\rMac OS9\rline endings.\nLast line") ; ;
1019
1020         file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
1021         if (sf_command (file, SFC_SET_BROADCAST_INFO, &bc_write, sizeof (bc_write)) == SF_FALSE)
1022         {       printf ("\n\nLine %d : sf_command (SFC_SET_BROADCAST_INFO) failed.\n\n", __LINE__) ;
1023                 exit (1) ;
1024                 } ;
1025
1026         test_write_double_or_die (file, 0, double_data, BUFFER_LEN, __LINE__) ;
1027         sf_close (file) ;
1028
1029         memset (&bc_read, 0, sizeof (bc_read)) ;
1030
1031         file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
1032         if (sf_command (file, SFC_GET_BROADCAST_INFO, &bc_read, sizeof (bc_read)) == SF_FALSE)
1033         {       printf ("\n\nLine %d : sf_command (SFC_SET_BROADCAST_INFO) failed.\n\n", __LINE__) ;
1034                 exit (1) ;
1035                 } ;
1036         check_log_buffer_or_die (file, __LINE__) ;
1037         sf_close (file) ;
1038
1039         if (bc_read.coding_history_size == 0)
1040         {       printf ("\n\nLine %d : missing coding history.\n\n", __LINE__) ;
1041                 exit (1) ;
1042                 } ;
1043
1044         if (strstr (bc_read.coding_history, "Last line") == NULL)
1045         {       printf ("\n\nLine %d : coding history truncated.\n\n", __LINE__) ;
1046                 exit (1) ;
1047                 } ;
1048
1049         for (k = 1 ; k < bc_read.coding_history_size ; k++)
1050         {       if (bc_read.coding_history [k] == '\n' && bc_read.coding_history [k - 1] != '\r')
1051                 {       printf ("\n\nLine %d : '\\n' without '\\r' before.\n\n", __LINE__) ;
1052                         exit (1) ;
1053                         } ;
1054
1055                 if (bc_read.coding_history [k] == '\r' && bc_read.coding_history [k + 1] != '\n')
1056                 {       printf ("\n\nLine %d : '\\r' without '\\n' after.\n\n", __LINE__) ;
1057                         exit (1) ;
1058                         } ;
1059
1060                 if (bc_read.coding_history [k] == 0 && k < bc_read.coding_history_size - 1)
1061                 {       printf ("\n\nLine %d : '\\0' within coding history at index %d of %d.\n\n", __LINE__, k, bc_read.coding_history_size) ;
1062                         exit (1) ;
1063                         } ;
1064                 } ;
1065
1066         return ;
1067 } /* check_coding_history_newlines */
1068
1069 static void
1070 broadcast_coding_history_test (const char *filename)
1071 {       static SF_BROADCAST_INFO bc_write, bc_read ;
1072         SNDFILE *file ;
1073         SF_INFO sfinfo ;
1074         const char *default_history = "A=PCM,F=22050,W=16,M=mono" ;
1075         const char *supplied_history =
1076                                         "A=PCM,F=44100,W=24,M=mono,T=other\r\n"
1077                                         "A=PCM,F=22050,W=16,M=mono,T=yet_another\r\n" ;
1078
1079         print_test_name ("broadcast_coding_history_test", filename) ;
1080
1081         sfinfo.samplerate       = 22050 ;
1082         sfinfo.format           = SF_FORMAT_WAV | SF_FORMAT_PCM_16 ;
1083         sfinfo.channels         = 1 ;
1084
1085         memset (&bc_write, 0, sizeof (bc_write)) ;
1086
1087         snprintf (bc_write.description, sizeof (bc_write.description), "Test description") ;
1088         snprintf (bc_write.originator, sizeof (bc_write.originator), "Test originator") ;
1089         snprintf (bc_write.originator_reference, sizeof (bc_write.originator_reference), "%08x-%08x", (unsigned int) time (NULL), (unsigned int) (~ time (NULL))) ;
1090         snprintf (bc_write.origination_date, sizeof (bc_write.origination_date), "%d/%02d/%02d", 2006, 3, 30) ;
1091         snprintf (bc_write.origination_time, sizeof (bc_write.origination_time), "%02d:%02d:%02d", 20, 27, 0) ;
1092         snprintf (bc_write.umid, sizeof (bc_write.umid), "Some umid") ;
1093         /* Coding history will be filled in by the library. */
1094         bc_write.coding_history_size = 0 ;
1095
1096         file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
1097         if (sf_command (file, SFC_SET_BROADCAST_INFO, &bc_write, sizeof (bc_write)) == SF_FALSE)
1098         {       printf ("\n\nLine %d : sf_command (SFC_SET_BROADCAST_INFO) failed.\n\n", __LINE__) ;
1099                 exit (1) ;
1100                 } ;
1101
1102         test_write_double_or_die (file, 0, double_data, BUFFER_LEN, __LINE__) ;
1103         sf_close (file) ;
1104
1105         memset (&bc_read, 0, sizeof (bc_read)) ;
1106
1107         file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
1108         if (sf_command (file, SFC_GET_BROADCAST_INFO, &bc_read, sizeof (bc_read)) == SF_FALSE)
1109         {       printf ("\n\nLine %d : sf_command (SFC_SET_BROADCAST_INFO) failed.\n\n", __LINE__) ;
1110                 exit (1) ;
1111                 } ;
1112         check_log_buffer_or_die (file, __LINE__) ;
1113         sf_close (file) ;
1114
1115         if (bc_read.coding_history_size == 0)
1116         {       printf ("\n\nLine %d : missing coding history.\n\n", __LINE__) ;
1117                 exit (1) ;
1118                 } ;
1119
1120         if (bc_read.coding_history_size < strlen (default_history) || memcmp (bc_read.coding_history, default_history, strlen (default_history)) != 0)
1121         {       printf ("\n\n"
1122                                 "Line %d : unexpected coding history '%.*s',\n"
1123                                 "            should be '%s'\n\n", __LINE__, bc_read.coding_history_size, bc_read.coding_history, default_history) ;
1124                 exit (1) ;
1125                 } ;
1126
1127         bc_write.coding_history_size = strlen (supplied_history) ;
1128         bc_write.coding_history_size = snprintf (bc_write.coding_history, sizeof (bc_write.coding_history), "%s", supplied_history) ;
1129
1130         file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
1131         if (sf_command (file, SFC_SET_BROADCAST_INFO, &bc_write, sizeof (bc_write)) == SF_FALSE)
1132         {       printf ("\n\nLine %d : sf_command (SFC_SET_BROADCAST_INFO) failed.\n\n", __LINE__) ;
1133                 exit (1) ;
1134                 } ;
1135
1136         test_write_double_or_die (file, 0, double_data, BUFFER_LEN, __LINE__) ;
1137         sf_close (file) ;
1138
1139         memset (&bc_read, 0, sizeof (bc_read)) ;
1140
1141         file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
1142         if (sf_command (file, SFC_GET_BROADCAST_INFO, &bc_read, sizeof (bc_read)) == SF_FALSE)
1143         {       printf ("\n\nLine %d : sf_command (SFC_SET_BROADCAST_INFO) failed.\n\n", __LINE__) ;
1144                 exit (1) ;
1145                 } ;
1146
1147         check_log_buffer_or_die (file, __LINE__) ;
1148         sf_close (file) ;
1149
1150         if (strstr (bc_read.coding_history, supplied_history) != bc_read.coding_history)
1151         {       printf ("\n\nLine %d : unexpected coding history :\n"
1152                                 "----------------------------------------------------\n%s"
1153                                 "----------------------------------------------------\n"
1154                                 "should be this :\n"
1155                                 "----------------------------------------------------\n%s"
1156                                 "----------------------------------------------------\n"
1157                                 "with one more line at the end.\n\n",
1158                                 __LINE__, bc_read.coding_history, supplied_history) ;
1159                 exit (1) ;
1160                 } ;
1161
1162         check_coding_history_newlines (filename) ;
1163
1164         unlink (filename) ;
1165         puts ("ok") ;
1166 } /* broadcast_coding_history_test */
1167
1168 /*==============================================================================
1169 */
1170
1171 static void
1172 broadcast_coding_history_size (const char *filename)
1173 {       /* SF_BROADCAST_INFO struct with coding_history field of 1024 bytes. */
1174         static SF_BROADCAST_INFO_VAR (1024) bc_write ;
1175         static SF_BROADCAST_INFO_VAR (1024) bc_read ;
1176         SNDFILE *file ;
1177         SF_INFO sfinfo ;
1178         int k ;
1179
1180         print_test_name (__func__, filename) ;
1181
1182         sfinfo.samplerate       = 22050 ;
1183         sfinfo.format           = SF_FORMAT_WAV | SF_FORMAT_PCM_16 ;
1184         sfinfo.channels         = 1 ;
1185
1186         memset (&bc_write, 0, sizeof (bc_write)) ;
1187
1188         snprintf (bc_write.description, sizeof (bc_write.description), "Test description") ;
1189         snprintf (bc_write.originator, sizeof (bc_write.originator), "Test originator") ;
1190         snprintf (bc_write.originator_reference, sizeof (bc_write.originator_reference), "%08x-%08x", (unsigned int) time (NULL), (unsigned int) (~ time (NULL))) ;
1191         snprintf (bc_write.origination_date, sizeof (bc_write.origination_date), "%d/%02d/%02d", 2006, 3, 30) ;
1192         snprintf (bc_write.origination_time, sizeof (bc_write.origination_time), "%02d:%02d:%02d", 20, 27, 0) ;
1193         snprintf (bc_write.umid, sizeof (bc_write.umid), "Some umid") ;
1194         bc_write.coding_history_size = 0 ;
1195
1196         for (k = 0 ; bc_write.coding_history_size < 512 ; k++)
1197         {       snprintf (bc_write.coding_history + bc_write.coding_history_size,
1198                         sizeof (bc_write.coding_history) - bc_write.coding_history_size, "line %4d\n", k) ;
1199                 bc_write.coding_history_size = strlen (bc_write.coding_history) ;
1200                 } ;
1201
1202         exit_if_true (bc_write.coding_history_size < 512,
1203                         "\n\nLine %d : bc_write.coding_history_size (%d) should be > 512.\n\n", __LINE__, bc_write.coding_history_size) ;
1204
1205         file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
1206         if (sf_command (file, SFC_SET_BROADCAST_INFO, &bc_write, sizeof (bc_write)) == SF_FALSE)
1207         {       printf ("\n\nLine %d : sf_command (SFC_SET_BROADCAST_INFO) failed.\n\n", __LINE__) ;
1208                 exit (1) ;
1209                 } ;
1210
1211         test_write_double_or_die (file, 0, double_data, BUFFER_LEN, __LINE__) ;
1212         sf_close (file) ;
1213
1214         memset (&bc_read, 0, sizeof (bc_read)) ;
1215
1216         file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
1217         if (sf_command (file, SFC_GET_BROADCAST_INFO, &bc_read, sizeof (bc_read)) == SF_FALSE)
1218         {       printf ("\n\nLine %d : sf_command (SFC_SET_BROADCAST_INFO) failed.\n\n", __LINE__) ;
1219                 exit (1) ;
1220                 } ;
1221         check_log_buffer_or_die (file, __LINE__) ;
1222         sf_close (file) ;
1223
1224         exit_if_true (bc_read.coding_history_size < 512,
1225                         "\n\nLine %d : unexpected coding history size %d (should be > 512).\n\n", __LINE__, bc_read.coding_history_size) ;
1226
1227         exit_if_true (strstr (bc_read.coding_history, "libsndfile") == NULL,
1228                         "\n\nLine %d : coding history incomplete (should contain 'libsndfile').\n\n", __LINE__) ;
1229
1230         unlink (filename) ;
1231         puts ("ok") ;
1232 } /* broadcast_coding_history_size */
1233
1234 /*==============================================================================
1235 */
1236 static void
1237 cart_test (const char *filename, int filetype)
1238 {       static SF_CART_INFO ca_write, ca_read ;
1239         SNDFILE *file ;
1240         SF_INFO sfinfo ;
1241         int errors = 0 ;
1242
1243         print_test_name ("cart_test", filename) ;
1244
1245         sfinfo.samplerate       = 11025 ;
1246         sfinfo.format           = filetype ;
1247         sfinfo.channels         = 1 ;
1248         memset (&ca_write, 0, sizeof (ca_write)) ;
1249
1250         // example test data
1251         snprintf (ca_write.artist, sizeof (ca_write.artist), "Test artist") ;
1252         snprintf (ca_write.version, sizeof (ca_write.version), "Test version") ;
1253         snprintf (ca_write.cut_id, sizeof (ca_write.cut_id), "Test cut ID") ;
1254         snprintf (ca_write.client_id, sizeof (ca_write.client_id), "Test client ID") ;
1255         snprintf (ca_write.category, sizeof (ca_write.category), "Test category") ;
1256         snprintf (ca_write.classification, sizeof (ca_write.classification), "Test classification") ;
1257         snprintf (ca_write.out_cue, sizeof (ca_write.out_cue), "Test out cue") ;
1258         snprintf (ca_write.start_date, sizeof (ca_write.start_date), "%d/%02d/%02d", 2006, 3, 30) ;
1259         snprintf (ca_write.start_time, sizeof (ca_write.start_time), "%02d:%02d:%02d", 20, 27, 0) ;
1260         snprintf (ca_write.end_date, sizeof (ca_write.end_date), "%d/%02d/%02d", 2006, 3, 30) ;
1261         snprintf (ca_write.end_time, sizeof (ca_write.end_time), "%02d:%02d:%02d", 20, 27, 0) ;
1262         snprintf (ca_write.producer_app_id, sizeof (ca_write.producer_app_id), "Test producer app id") ;
1263         snprintf (ca_write.producer_app_version, sizeof (ca_write.producer_app_version), "Test producer app version") ;
1264         snprintf (ca_write.user_def, sizeof (ca_write.user_def), "test user def test test") ;
1265         ca_write.level_reference = 42 ;
1266         snprintf (ca_write.url, sizeof (ca_write.url), "http://www.test.com/test_url") ;
1267         snprintf (ca_write.tag_text, sizeof (ca_write.tag_text), "tag text test! \r\n") ; // must be terminated \r\n to be valid
1268         ca_write.tag_text_size = strlen (ca_write.tag_text) ;
1269
1270         file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
1271         if (sf_command (file, SFC_SET_CART_INFO, &ca_write, sizeof (ca_write)) == SF_FALSE)
1272                 exit (1) ;
1273
1274         test_write_double_or_die (file, 0, double_data, BUFFER_LEN, __LINE__) ;
1275         sf_close (file) ;
1276
1277         memset (&ca_read, 0, sizeof (ca_read)) ;
1278
1279         file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
1280         if (sf_command (file, SFC_GET_CART_INFO, &ca_read, sizeof (ca_read)) == SF_FALSE)
1281         {       printf ("\n\nLine %d : sf_command (SFC_GET_CART_INFO) failed.\n\n", __LINE__) ;
1282                 exit (1) ;
1283                 return ;
1284                 } ;
1285         check_log_buffer_or_die (file, __LINE__) ;
1286         sf_close (file) ;
1287
1288
1289         if (memcmp (ca_write.artist, ca_read.artist, sizeof (ca_write.artist)) != 0)
1290         {       printf ("\n\nLine %d : artist mismatch :\n\twrite : '%s'\n\tread  : '%s'\n\n", __LINE__, ca_write.artist, ca_read.artist) ;
1291                 errors ++ ;
1292                 } ;
1293
1294         if (memcmp (ca_write.version, ca_read.version, sizeof (ca_write.version)) != 0)
1295         {       printf ("\n\nLine %d : version mismatch :\n\twrite : '%s'\n\tread  : '%s'\n\n", __LINE__, ca_write.version, ca_read.version) ;
1296                 errors ++ ;
1297                 } ;
1298
1299         if (memcmp (ca_write.title, ca_read.title, sizeof (ca_write.title)) != 0)
1300         {       printf ("\n\nLine %d : title mismatch :\n\twrite : '%s'\n\tread  : '%s'\n\n", __LINE__, ca_write.title, ca_read.title) ;
1301                 errors ++ ;
1302                 } ;
1303
1304         if (memcmp (ca_write.cut_id, ca_read.cut_id, sizeof (ca_write.cut_id)) != 0)
1305         {       printf ("\n\nLine %d : cut_id mismatch :\n\twrite : '%s'\n\tread  : '%s'\n\n", __LINE__, ca_write.cut_id, ca_read.cut_id) ;
1306                 errors ++ ;
1307                 } ;
1308
1309         if (memcmp (ca_write.client_id, ca_read.client_id, sizeof (ca_write.client_id)) != 0)
1310         {       printf ("\n\nLine %d : client_id mismatch :\n\twrite : '%s'\n\tread  : '%s'\n\n", __LINE__, ca_write.client_id, ca_read.client_id) ;
1311                 errors ++ ;
1312                 } ;
1313
1314         if (memcmp (ca_write.category, ca_read.category, sizeof (ca_write.category)) != 0)
1315         {       printf ("\n\nLine %d : category mismatch :\n\twrite : '%s'\n\tread  : '%s'\n\n", __LINE__, ca_write.category, ca_read.category) ;
1316                 errors ++ ;
1317                 } ;
1318
1319         if (memcmp (ca_write.out_cue, ca_read.out_cue, sizeof (ca_write.out_cue)) != 0)
1320         {       printf ("\n\nLine %d : out_cue mismatch :\n\twrite : '%s'\n\tread  : '%s'\n\n", __LINE__, ca_write.out_cue, ca_read.out_cue) ;
1321                 errors ++ ;
1322                 } ;
1323
1324         if (memcmp (ca_write.start_date, ca_read.start_date, sizeof (ca_write.start_date)) != 0)
1325         {       printf ("\n\nLine %d : start_date mismatch :\n\twrite : '%s'\n\tread  : '%s'\n\n", __LINE__, ca_write.start_date, ca_read.start_date) ;
1326                 errors ++ ;
1327                 } ;
1328
1329
1330         if (memcmp (ca_write.start_time, ca_read.start_time, sizeof (ca_write.start_time)) != 0)
1331         {       printf ("\n\nLine %d : start_time mismatch :\n\twrite : '%s'\n\tread  : '%s'\n\n", __LINE__, ca_write.start_time, ca_read.start_time) ;
1332                 errors ++ ;
1333                 } ;
1334
1335
1336         if (memcmp (ca_write.end_date, ca_read.end_date, sizeof (ca_write.end_date)) != 0)
1337         {       printf ("\n\nLine %d : end_date mismatch :\n\twrite : '%s'\n\tread  : '%s'\n\n", __LINE__, ca_write.end_date, ca_read.end_date) ;
1338                 errors ++ ;
1339                 } ;
1340
1341
1342         if (memcmp (ca_write.end_time, ca_read.end_time, sizeof (ca_write.end_time)) != 0)
1343         {       printf ("\n\nLine %d : end_time mismatch :\n\twrite : '%s'\n\tread  : '%s'\n\n", __LINE__, ca_write.end_time, ca_read.end_time) ;
1344                 errors ++ ;
1345                 } ;
1346
1347
1348         if (memcmp (ca_write.producer_app_id, ca_read.producer_app_id, sizeof (ca_write.producer_app_id)) != 0)
1349         {       printf ("\n\nLine %d : producer_app_id mismatch :\n\twrite : '%s'\n\tread  : '%s'\n\n", __LINE__, ca_write.producer_app_id, ca_read.producer_app_id) ;
1350                 errors ++ ;
1351                 } ;
1352
1353
1354         if (memcmp (ca_write.producer_app_version, ca_read.producer_app_version, sizeof (ca_write.producer_app_version)) != 0)
1355         {       printf ("\n\nLine %d : producer_app_version mismatch :\n\twrite : '%s'\n\tread  : '%s'\n\n", __LINE__, ca_write.producer_app_version, ca_read.producer_app_version) ;
1356                 errors ++ ;
1357                 } ;
1358
1359
1360         if (memcmp (ca_write.user_def, ca_read.user_def, sizeof (ca_write.user_def)) != 0)
1361         {       printf ("\n\nLine %d : user_def mismatch :\n\twrite : '%s'\n\tread  : '%s'\n\n", __LINE__, ca_write.user_def, ca_read.user_def) ;
1362                 errors ++ ;
1363                 } ;
1364
1365
1366         if (ca_write.level_reference != ca_read.level_reference)
1367         {       printf ("\n\nLine %d : level_reference mismatch :\n\twrite : '%d'\n\tread  : '%d'\n\n", __LINE__, ca_write.level_reference, ca_read.level_reference) ;
1368                 errors ++ ;
1369                 } ;
1370
1371         // TODO: make this more helpful
1372         if (memcmp (ca_write.post_timers, ca_read.post_timers, sizeof (ca_write.post_timers)) != 0)
1373         {       printf ("\n\nLine %d : post_timers mismatch :\n'\n\n", __LINE__) ;
1374                 errors ++ ;
1375                 } ;
1376
1377         if (memcmp (ca_write.url, ca_read.url, sizeof (ca_write.url)) != 0)
1378         {       printf ("\n\nLine %d : url mismatch :\n\twrite : '%s'\n\tread  : '%s'\n\n", __LINE__, ca_write.url, ca_read.url) ;
1379                 errors ++ ;
1380                 } ;
1381
1382
1383         if (memcmp (ca_write.tag_text, ca_read.tag_text, (size_t) (ca_read.tag_text_size)) != 0)
1384         {       printf ("\n\nLine %d : tag_text mismatch :\n\twrite : '%s'\n\tread  : '%s'\n\n", __LINE__, ca_write.tag_text, ca_read.tag_text) ;
1385                 errors ++ ;
1386                 } ;
1387
1388
1389         if (errors)
1390                 exit (1) ;
1391
1392         unlink (filename) ;
1393         puts ("ok") ;
1394 } /* cart_test */
1395
1396 static  void
1397 cart_rdwr_test (const char *filename, int filetype)
1398 {       SF_CART_INFO cinfo ;
1399         SNDFILE *file ;
1400         SF_INFO sfinfo ;
1401         sf_count_t frames ;
1402
1403         print_test_name (__func__, filename) ;
1404
1405         create_short_sndfile (filename, filetype, 2) ;
1406
1407         memset (&sfinfo, 0, sizeof (sfinfo)) ;
1408         memset (&cinfo, 0, sizeof (cinfo)) ;
1409
1410         snprintf (cinfo.artist, sizeof (cinfo.artist), "Test artist") ;
1411         snprintf (cinfo.version, sizeof (cinfo.version), "Test version") ;
1412         snprintf (cinfo.cut_id, sizeof (cinfo.cut_id), "Test cut ID") ;
1413         snprintf (cinfo.client_id, sizeof (cinfo.client_id), "Test client ID") ;
1414         snprintf (cinfo.category, sizeof (cinfo.category), "Test category") ;
1415         snprintf (cinfo.classification, sizeof (cinfo.classification), "Test classification") ;
1416         snprintf (cinfo.out_cue, sizeof (cinfo.out_cue), "Test out cue") ;
1417         snprintf (cinfo.start_date, sizeof (cinfo.start_date), "%d/%02d/%02d", 2006, 3, 30) ;
1418         snprintf (cinfo.start_time, sizeof (cinfo.start_time), "%02d:%02d:%02d", 20, 27, 0) ;
1419         snprintf (cinfo.end_date, sizeof (cinfo.end_date), "%d/%02d/%02d", 2006, 3, 30) ;
1420         snprintf (cinfo.end_time, sizeof (cinfo.end_time), "%02d:%02d:%02d", 20, 27, 0) ;
1421         snprintf (cinfo.producer_app_id, sizeof (cinfo.producer_app_id), "Test producer app id") ;
1422         snprintf (cinfo.producer_app_version, sizeof (cinfo.producer_app_version), "Test producer app version") ;
1423         snprintf (cinfo.user_def, sizeof (cinfo.user_def), "test user def test test") ;
1424         cinfo.level_reference = 42 ;
1425         snprintf (cinfo.url, sizeof (cinfo.url), "http://www.test.com/test_url") ;
1426         snprintf (cinfo.tag_text, sizeof (cinfo.tag_text), "tag text test!\r\n") ;
1427         cinfo.tag_text_size = strlen (cinfo.tag_text) ;
1428
1429         file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_TRUE, __LINE__) ;
1430         frames = sfinfo.frames ;
1431         if (sf_command (file, SFC_SET_CART_INFO, &cinfo, sizeof (cinfo)) != SF_FALSE)
1432         {       printf ("\n\nLine %d : sf_command (SFC_SET_CART_INFO) should have failed but didn't.\n\n", __LINE__) ;
1433                 exit (1) ;
1434                 } ;
1435         sf_close (file) ;
1436
1437         file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
1438         sf_close (file) ;
1439         exit_if_true (frames != sfinfo.frames, "\n\nLine %d : Frame count %" PRId64 " should be %" PRId64 ".\n", __LINE__, sfinfo.frames, frames) ;
1440
1441         unlink (filename) ;
1442         puts ("ok") ;
1443 } /* cart_rdwr_test */
1444
1445 /*==============================================================================
1446 */
1447
1448 static  void
1449 channel_map_test (const char *filename, int filetype)
1450 {       SNDFILE *file ;
1451         SF_INFO sfinfo ;
1452         int channel_map_read [4], channel_map_write [4] =
1453         {       SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_LFE,
1454                 SF_CHANNEL_MAP_REAR_CENTER
1455                 } ;
1456
1457         print_test_name ("channel_map_test", filename) ;
1458
1459         memset (&sfinfo, 0, sizeof (sfinfo)) ;
1460         sfinfo.samplerate       = 11025 ;
1461         sfinfo.format           = filetype ;
1462         sfinfo.channels         = ARRAY_LEN (channel_map_read) ;
1463
1464         switch (filetype & SF_FORMAT_TYPEMASK)
1465         {       /* WAVEX and RF64 have a default channel map, even if you don't specify one. */
1466                 case SF_FORMAT_WAVEX :
1467                 case SF_FORMAT_RF64 :
1468                         /* Write file without channel map. */
1469                         file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
1470                         test_write_double_or_die (file, 0, double_data, BUFFER_LEN, __LINE__) ;
1471                         sf_close (file) ;
1472
1473                         /* Read file making default channel map exists. */
1474                         file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
1475                         exit_if_true (
1476                                 sf_command (file, SFC_GET_CHANNEL_MAP_INFO, channel_map_read, sizeof (channel_map_read)) == SF_FALSE,
1477                                 "\n\nLine %d : sf_command (SFC_GET_CHANNEL_MAP_INFO) should not have failed.\n\n", __LINE__
1478                                 ) ;
1479                         check_log_buffer_or_die (file, __LINE__) ;
1480                         sf_close (file) ;
1481                         break ;
1482
1483                 default :
1484                         break ;
1485                 } ;
1486
1487         /* Write file with a channel map. */
1488         file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
1489         exit_if_true (
1490                 sf_command (file, SFC_SET_CHANNEL_MAP_INFO, channel_map_write, sizeof (channel_map_write)) == SF_FALSE,
1491                 "\n\nLine %d : sf_command (SFC_SET_CHANNEL_MAP_INFO) failed.\n\n", __LINE__
1492                 ) ;
1493         test_write_double_or_die (file, 0, double_data, BUFFER_LEN, __LINE__) ;
1494         sf_close (file) ;
1495
1496         /* Read file making sure no channel map exists. */
1497         file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
1498         exit_if_true (
1499                 sf_command (file, SFC_GET_CHANNEL_MAP_INFO, channel_map_read, sizeof (channel_map_read)) != SF_TRUE,
1500                 "\n\nLine %d : sf_command (SFC_GET_CHANNEL_MAP_INFO) failed.\n\n", __LINE__
1501                 ) ;
1502         check_log_buffer_or_die (file, __LINE__) ;
1503         sf_close (file) ;
1504
1505         exit_if_true (
1506                 memcmp (channel_map_read, channel_map_write, sizeof (channel_map_read)) != 0,
1507                 "\n\nLine %d : Channel map read does not match channel map written.\n\n", __LINE__
1508                 ) ;
1509
1510         unlink (filename) ;
1511         puts ("ok") ;
1512 } /* channel_map_test */
1513
1514 static  void
1515 raw_needs_endswap_test (const char *filename, int filetype)
1516 {       static int subtypes [] =
1517         {       SF_FORMAT_FLOAT, SF_FORMAT_DOUBLE,
1518                 SF_FORMAT_PCM_16, SF_FORMAT_PCM_24, SF_FORMAT_PCM_32
1519                 } ;
1520         SNDFILE *file ;
1521         SF_INFO sfinfo ;
1522         unsigned k ;
1523         int needs_endswap ;
1524
1525         print_test_name (__func__, filename) ;
1526
1527         for (k = 0 ; k < ARRAY_LEN (subtypes) ; k++)
1528         {
1529                 if (filetype == (SF_ENDIAN_LITTLE | SF_FORMAT_AIFF))
1530                         switch (subtypes [k])
1531                         {       /* Little endian AIFF does not AFAIK support fl32 and fl64. */
1532                                 case SF_FORMAT_FLOAT :
1533                                 case SF_FORMAT_DOUBLE :
1534                                         continue ;
1535                                 default :
1536                                         break ;
1537                                 } ;
1538
1539                 memset (&sfinfo, 0, sizeof (sfinfo)) ;
1540                 sfinfo.samplerate       = 11025 ;
1541                 sfinfo.format           = filetype | subtypes [k] ;
1542                 sfinfo.channels         = 1 ;
1543
1544                 file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
1545                 test_write_double_or_die (file, 0, double_data, BUFFER_LEN, __LINE__) ;
1546                 sf_close (file) ;
1547
1548                 memset (&sfinfo, 0, sizeof (sfinfo)) ;
1549                 file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
1550
1551                 needs_endswap = sf_command (file, SFC_RAW_DATA_NEEDS_ENDSWAP, NULL, 0) ;
1552
1553                 switch (filetype)
1554                 {       case SF_FORMAT_WAV :
1555                         case SF_FORMAT_WAVEX :
1556                         case SF_FORMAT_AIFF | SF_ENDIAN_LITTLE :
1557                                 exit_if_true (needs_endswap != CPU_IS_BIG_ENDIAN,
1558                                         "\n\nLine %d : SFC_RAW_DATA_NEEDS_ENDSWAP failed for (%d | %d).\n\n", __LINE__, filetype, k) ;
1559                                 break ;
1560
1561                         case SF_FORMAT_AIFF :
1562                         case SF_FORMAT_WAV | SF_ENDIAN_BIG :
1563                                 exit_if_true (needs_endswap != CPU_IS_LITTLE_ENDIAN,
1564                                         "\n\nLine %d : SFC_RAW_DATA_NEEDS_ENDSWAP failed for (%d | %d).\n\n", __LINE__, filetype, k) ;
1565                                 break ;
1566
1567                         default :
1568                                 printf ("\n\nLine %d : bad format value %d.\n\n", __LINE__, filetype) ;
1569                                 exit (1) ;
1570                                 break ;
1571                         } ;
1572
1573                 sf_close (file) ;
1574                 } ;
1575
1576         unlink (filename) ;
1577         puts ("ok") ;
1578 } /* raw_needs_endswap_test */