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