e871760e0dd5c8bd3e89b1c95186da9171002fa3
[platform/upstream/libsndfile.git] / tests / lossy_comp_test.c
1 /*
2 ** Copyright (C) 1999-2011 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 <string.h>
24 #include <math.h>
25
26 #if HAVE_UNISTD_H
27 #include <unistd.h>
28 #endif
29
30 #include <sndfile.h>
31
32 #include "utils.h"
33
34 #define BUFFER_SIZE             (1<<14) /* Should be (1<<14) */
35 #define SAMPLE_RATE             11025
36
37 #ifndef         M_PI
38 #define         M_PI            3.14159265358979323846264338
39 #endif
40
41 #define         LCT_MAX(x,y)    ((x) > (y) ? (x) : (y))
42
43 static  void    lcomp_test_short        (const char *filename, int filetype, int chan, double margin) ;
44 static  void    lcomp_test_int          (const char *filename, int filetype, int chan, double margin) ;
45 static  void    lcomp_test_float        (const char *filename, int filetype, int chan, double margin) ;
46 static  void    lcomp_test_double       (const char *filename, int filetype, int chan, double margin) ;
47
48 static  void    sdlcomp_test_short      (const char *filename, int filetype, int chan, double margin) ;
49 static  void    sdlcomp_test_int        (const char *filename, int filetype, int chan, double margin) ;
50 static  void    sdlcomp_test_float      (const char *filename, int filetype, int chan, double margin) ;
51 static  void    sdlcomp_test_double     (const char *filename, int filetype, int chan, double margin) ;
52
53 static void             read_raw_test (const char *filename, int filetype, int chan) ;
54
55 static  int             error_function (double data, double orig, double margin) ;
56 static  int             decay_response (int k) ;
57
58 static  void    gen_signal_double (double *data, double scale, int channels, int datalen) ;
59
60 static  void    smoothed_diff_short (short *data, unsigned int datalen) ;
61 static  void    smoothed_diff_int (int *data, unsigned int datalen) ;
62 static  void    smoothed_diff_float (float *data, unsigned int datalen) ;
63 static  void    smoothed_diff_double (double *data, unsigned int datalen) ;
64
65 static void             check_comment (SNDFILE * file, int format, int lineno) ;
66
67 static int              is_lossy (int filetype) ;
68
69 /*
70 ** Force the start of these buffers to be double aligned. Sparc-solaris will
71 ** choke if they are not.
72 */
73 typedef union
74 {       double  d [BUFFER_SIZE + 1] ;
75         float   f [BUFFER_SIZE + 1] ;
76         int             i [BUFFER_SIZE + 1] ;
77         short   s [BUFFER_SIZE + 1] ;
78         char    c [BUFFER_SIZE + 1] ;
79 } BUFFER ;
80
81 static  BUFFER  data_buffer ;
82 static  BUFFER  orig_buffer ;
83 static  BUFFER  smooth_buffer ;
84
85 static const char *long_comment =
86         "This is really quite a long comment. It is designed to be long enough "
87         "to screw up the encoders and decoders if the file container format does "
88         "not handle things correctly. If everything is working correctly, the "
89         "decoder will only decode the actual audio data, and not this string at "
90         "the end of the file." ;
91
92 int
93 main (int argc, char *argv [])
94 {       int             do_all = 0 ;
95         int             test_count = 0 ;
96
97         if (argc != 2)
98         {       printf ("Usage : %s <test>\n", argv [0]) ;
99                 printf ("    Where <test> is one of the following:\n") ;
100                 printf ("           wav_ima     - test IMA ADPCM WAV file functions\n") ;
101                 printf ("           wav_msadpcm - test MS ADPCM WAV file functions\n") ;
102                 printf ("           wav_gsm610  - test GSM 6.10 WAV file functions\n") ;
103                 printf ("           wav_ulaw    - test u-law WAV file functions\n") ;
104                 printf ("           wav_alaw    - test A-law WAV file functions\n") ;
105                 printf ("           wve         - test Psion WVE file functions\n") ;
106                 printf ("           all         - perform all tests\n") ;
107                 exit (1) ;
108                 } ;
109
110         do_all = ! strcmp (argv [1], "all") ;
111
112         if (do_all || strcmp (argv [1], "wav_pcm") == 0)
113         {       /* This is just a sanity test for PCM encoding. */
114                 lcomp_test_short        ("pcm.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_16, 2, 1e-50) ;
115                 lcomp_test_int          ("pcm.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_32, 2, 1e-50) ;
116                 lcomp_test_short        ("pcm.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_PCM_16, 2, 1e-50) ;
117                 lcomp_test_int          ("pcm.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_PCM_32, 2, 1e-50) ;
118                 /* Lite remove start */
119                 lcomp_test_float        ("pcm.wav", SF_FORMAT_WAV | SF_FORMAT_FLOAT, 2, 1e-50) ;
120                 lcomp_test_double       ("pcm.wav", SF_FORMAT_WAV | SF_FORMAT_DOUBLE, 2, 1e-50) ;
121                 /* Lite remove end */
122
123                 read_raw_test ("pcm.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_U8, 2) ;
124                 test_count++ ;
125                 } ;
126
127         /* For all the rest, if the file format supports more than 1 channel, use stereo. */
128         /* Lite remove start */
129         if (do_all || strcmp (argv [1], "wav_ima") == 0)
130         {       lcomp_test_short        ("ima.wav", SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
131                 lcomp_test_int          ("ima.wav", SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM, 2, 0.65) ;
132                 lcomp_test_float        ("ima.wav", SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
133                 lcomp_test_double       ("ima.wav", SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
134
135                 lcomp_test_short        ("ima.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
136                 lcomp_test_int          ("ima.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
137                 lcomp_test_float        ("ima.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
138                 lcomp_test_double       ("ima.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
139
140                 sdlcomp_test_short      ("ima.wav", SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
141                 sdlcomp_test_int        ("ima.wav", SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
142                 sdlcomp_test_float      ("ima.wav", SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
143                 sdlcomp_test_double     ("ima.wav", SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
144                 test_count++ ;
145                 } ;
146
147         if (do_all || strcmp (argv [1], "wav_msadpcm") == 0)
148         {       lcomp_test_short        ("msadpcm.wav", SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
149                 lcomp_test_int          ("msadpcm.wav", SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
150                 lcomp_test_float        ("msadpcm.wav", SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
151                 lcomp_test_double       ("msadpcm.wav", SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
152
153                 lcomp_test_short        ("msadpcm.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
154                 lcomp_test_int          ("msadpcm.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
155                 lcomp_test_float        ("msadpcm.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
156                 lcomp_test_double       ("msadpcm.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
157
158                 sdlcomp_test_short      ("msadpcm.wav", SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
159                 sdlcomp_test_int        ("msadpcm.wav", SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
160                 sdlcomp_test_float      ("msadpcm.wav", SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
161                 sdlcomp_test_double     ("msadpcm.wav", SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
162
163                 test_count++ ;
164                 } ;
165
166         if (do_all || strcmp (argv [1], "wav_g721") == 0)
167         {       printf ("**** Fix this later : error bound should be 0.06 ****\n") ;
168                 lcomp_test_short        ("g721.wav", SF_FORMAT_WAV | SF_FORMAT_G721_32, 1, 0.7) ;
169                 lcomp_test_int          ("g721.wav", SF_FORMAT_WAV | SF_FORMAT_G721_32, 1, 0.7) ;
170
171                 lcomp_test_short        ("g721.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_G721_32, 1, 0.7) ;
172                 lcomp_test_int          ("g721.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_G721_32, 1, 0.7) ;
173
174                 test_count++ ;
175                 } ;
176         /* Lite remove end */
177
178         if (do_all || strcmp (argv [1], "wav_ulaw") == 0)
179         {       lcomp_test_short        ("ulaw.wav", SF_FORMAT_WAV | SF_FORMAT_ULAW, 2, 0.04) ;
180                 lcomp_test_int          ("ulaw.wav", SF_FORMAT_WAV | SF_FORMAT_ULAW, 2, 0.04) ;
181
182                 lcomp_test_short        ("ulaw.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_ULAW, 2, 0.04) ;
183                 lcomp_test_int          ("ulaw.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_ULAW, 2, 0.04) ;
184
185                 /* Lite remove start */
186                 lcomp_test_float        ("ulaw.wav", SF_FORMAT_WAV | SF_FORMAT_ULAW, 2, 0.04) ;
187                 lcomp_test_double       ("ulaw.wav", SF_FORMAT_WAV | SF_FORMAT_ULAW, 2, 0.04) ;
188                 /* Lite remove end */
189
190                 read_raw_test ("ulaw.wav", SF_FORMAT_WAV | SF_FORMAT_ULAW, 2) ;
191                 test_count++ ;
192                 } ;
193
194         if (do_all || strcmp (argv [1], "wav_alaw") == 0)
195         {       lcomp_test_short        ("alaw.wav", SF_FORMAT_WAV | SF_FORMAT_ALAW, 2, 0.04) ;
196                 lcomp_test_int          ("alaw.wav", SF_FORMAT_WAV | SF_FORMAT_ALAW, 2, 0.04) ;
197                 /* Lite remove start */
198                 lcomp_test_float        ("alaw.wav", SF_FORMAT_WAV | SF_FORMAT_ALAW, 2, 0.04) ;
199                 lcomp_test_double       ("alaw.wav", SF_FORMAT_WAV | SF_FORMAT_ALAW, 2, 0.04) ;
200                 /* Lite remove end */
201
202                 read_raw_test ("alaw.wav", SF_FORMAT_WAV | SF_FORMAT_ALAW, 2) ;
203                 test_count++ ;
204                 } ;
205
206         if (do_all || strcmp (argv [1], "wav_gsm610") == 0)
207         {       /* Don't do lcomp_test_XXX as the errors are too big. */
208                 sdlcomp_test_short      ("gsm610.wav", SF_FORMAT_WAV | SF_FORMAT_GSM610, 1, 0.24) ;
209                 sdlcomp_test_int        ("gsm610.wav", SF_FORMAT_WAV | SF_FORMAT_GSM610, 1, 0.24) ;
210
211                 sdlcomp_test_short      ("gsm610.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_GSM610, 1, 0.24) ;
212                 sdlcomp_test_int        ("gsm610.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_GSM610, 1, 0.24) ;
213
214                 /* Lite remove start */
215                 sdlcomp_test_float      ("gsm610.wav", SF_FORMAT_WAV | SF_FORMAT_GSM610, 1, 0.24) ;
216                 sdlcomp_test_double     ("gsm610.wav", SF_FORMAT_WAV | SF_FORMAT_GSM610, 1, 0.24) ;
217                 /* Lite remove end */
218                 test_count++ ;
219                 } ;
220
221         if (do_all || strcmp (argv [1], "aiff_ulaw") == 0)
222         {       lcomp_test_short        ("ulaw.aiff", SF_FORMAT_AIFF | SF_FORMAT_ULAW, 2, 0.04) ;
223                 lcomp_test_int          ("ulaw.aiff", SF_FORMAT_AIFF | SF_FORMAT_ULAW, 2, 0.04) ;
224                 /* Lite remove start */
225                 lcomp_test_float        ("ulaw.aiff", SF_FORMAT_AIFF | SF_FORMAT_ULAW, 2, 0.04) ;
226                 lcomp_test_double       ("ulaw.aiff", SF_FORMAT_AIFF | SF_FORMAT_ULAW, 2, 0.04) ;
227                 /* Lite remove end */
228
229                 read_raw_test ("ulaw.aiff", SF_FORMAT_AIFF | SF_FORMAT_ULAW, 2) ;
230                 test_count++ ;
231                 } ;
232
233         if (do_all || strcmp (argv [1], "aiff_alaw") == 0)
234         {       lcomp_test_short        ("alaw.aiff", SF_FORMAT_AIFF | SF_FORMAT_ALAW, 2, 0.04) ;
235                 lcomp_test_int          ("alaw.aiff", SF_FORMAT_AIFF | SF_FORMAT_ALAW, 2, 0.04) ;
236                 /* Lite remove start */
237                 lcomp_test_float        ("alaw.aiff", SF_FORMAT_AIFF | SF_FORMAT_ALAW, 2, 0.04) ;
238                 lcomp_test_double       ("alaw.aiff", SF_FORMAT_AIFF | SF_FORMAT_ALAW, 2, 0.04) ;
239                 /* Lite remove end */
240
241                 read_raw_test ("alaw.aiff", SF_FORMAT_AIFF | SF_FORMAT_ALAW, 2) ;
242                 test_count++ ;
243                 } ;
244
245         if (do_all || strcmp (argv [1], "aiff_gsm610") == 0)
246         {       /* Don't do lcomp_test_XXX as the errors are too big. */
247                 sdlcomp_test_short      ("gsm610.aiff", SF_FORMAT_AIFF | SF_FORMAT_GSM610, 1, 0.24) ;
248                 sdlcomp_test_int        ("gsm610.aiff", SF_FORMAT_AIFF | SF_FORMAT_GSM610, 1, 0.24) ;
249                 /* Lite remove start */
250                 sdlcomp_test_float      ("gsm610.aiff", SF_FORMAT_AIFF | SF_FORMAT_GSM610, 1, 0.24) ;
251                 sdlcomp_test_double     ("gsm610.aiff", SF_FORMAT_AIFF | SF_FORMAT_GSM610, 1, 0.24) ;
252                 /* Lite remove end */
253                 test_count++ ;
254                 } ;
255
256         if (strcmp (argv [1], "aiff_ima") == 0)
257         {       lcomp_test_short        ("ima.aiff", SF_FORMAT_AIFF | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
258                 lcomp_test_int          ("ima.aiff", SF_FORMAT_AIFF | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
259                 /* Lite remove start */
260                 lcomp_test_float        ("ima.aiff", SF_FORMAT_AIFF | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
261                 lcomp_test_double       ("ima.aiff", SF_FORMAT_AIFF | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
262                 /* Lite remove end */
263                 } ;
264
265         if (do_all || strcmp (argv [1], "au_ulaw") == 0)
266         {       lcomp_test_short        ("ulaw.au", SF_ENDIAN_BIG               | SF_FORMAT_AU | SF_FORMAT_ULAW, 2, 0.04) ;
267                 lcomp_test_int          ("ulaw.au", SF_ENDIAN_LITTLE    | SF_FORMAT_AU | SF_FORMAT_ULAW, 2, 0.04) ;
268                 /* Lite remove start */
269                 lcomp_test_float        ("ulaw.au", SF_ENDIAN_LITTLE    | SF_FORMAT_AU | SF_FORMAT_ULAW, 2, 0.04) ;
270                 lcomp_test_double       ("ulaw.au", SF_ENDIAN_BIG               | SF_FORMAT_AU | SF_FORMAT_ULAW, 2, 0.04) ;
271                 /* Lite remove end */
272                 test_count++ ;
273                 } ;
274
275         if (do_all || strcmp (argv [1], "au_alaw") == 0)
276         {       lcomp_test_short        ("alaw.au", SF_ENDIAN_LITTLE    | SF_FORMAT_AU | SF_FORMAT_ALAW, 2, 0.04) ;
277                 lcomp_test_int          ("alaw.au", SF_ENDIAN_BIG               | SF_FORMAT_AU | SF_FORMAT_ALAW, 2, 0.04) ;
278                 /* Lite remove start */
279                 lcomp_test_float        ("alaw.au", SF_ENDIAN_BIG               | SF_FORMAT_AU | SF_FORMAT_ALAW, 2, 0.04) ;
280                 lcomp_test_double       ("alaw.au", SF_ENDIAN_LITTLE    | SF_FORMAT_AU | SF_FORMAT_ALAW, 2, 0.04) ;
281                 /* Lite remove end */
282                 test_count++ ;
283                 } ;
284
285         /* Lite remove start */
286         if (do_all || strcmp (argv [1], "au_g721") == 0)
287         {       printf ("**** Fix this later : error bound should be 0.06 ****\n") ;
288                 lcomp_test_short        ("g721.au", SF_ENDIAN_LITTLE    | SF_FORMAT_AU | SF_FORMAT_G721_32, 1, 0.7) ;
289                 lcomp_test_int          ("g721.au", SF_ENDIAN_BIG               | SF_FORMAT_AU | SF_FORMAT_G721_32, 1, 0.7) ;
290                 lcomp_test_float        ("g721.au", SF_ENDIAN_LITTLE    | SF_FORMAT_AU | SF_FORMAT_G721_32, 1, 0.7) ;
291                 lcomp_test_double       ("g721.au", SF_ENDIAN_BIG               | SF_FORMAT_AU | SF_FORMAT_G721_32, 1, 0.7) ;
292
293 /*-             sdlcomp_test_short      ("g721.au", SF_ENDIAN_BIG    | SF_FORMAT_AU | SF_FORMAT_G721_32, 1, 0.07) ;
294                 sdlcomp_test_int        ("g721.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_G721_32, 1, 0.07) ;
295                 sdlcomp_test_float  ("g721.au", SF_ENDIAN_BIG    | SF_FORMAT_AU | SF_FORMAT_G721_32, 1, 0.07) ;
296                 sdlcomp_test_double     ("g721.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_G721_32, 1, 0.12) ;
297 -*/
298                 test_count++ ;
299                 } ;
300
301         if (do_all || strcmp (argv [1], "au_g723") == 0)
302         {       printf ("**** Fix this later : error bound should be 0.16 ****\n") ;
303                 lcomp_test_short        ("g723_24.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_G723_24, 1, 0.7) ;
304                 lcomp_test_int          ("g723_24.au", SF_ENDIAN_BIG    | SF_FORMAT_AU | SF_FORMAT_G723_24, 1, 0.7) ;
305                 lcomp_test_float        ("g723_24.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_G723_24, 1, 0.7) ;
306                 lcomp_test_double       ("g723_24.au", SF_ENDIAN_BIG    | SF_FORMAT_AU | SF_FORMAT_G723_24, 1, 0.7) ;
307
308                 lcomp_test_short        ("g723_40.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_G723_40, 1, 0.85) ;
309                 lcomp_test_int          ("g723_40.au", SF_ENDIAN_BIG    | SF_FORMAT_AU | SF_FORMAT_G723_40, 1, 0.84) ;
310                 lcomp_test_float        ("g723_40.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_G723_40, 1, 0.86) ;
311                 lcomp_test_double       ("g723_40.au", SF_ENDIAN_BIG    | SF_FORMAT_AU | SF_FORMAT_G723_40, 1, 0.86) ;
312
313 /*-             sdlcomp_test_short      ("g723.au", SF_ENDIAN_BIG    | SF_FORMAT_AU | SF_FORMAT_G723_24, 1, 0.15) ;
314                 sdlcomp_test_int        ("g723.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_G723_24, 1, 0.15) ;
315                 sdlcomp_test_float      ("g723.au", SF_ENDIAN_BIG    | SF_FORMAT_AU | SF_FORMAT_G723_24, 1, 0.15) ;
316                 sdlcomp_test_double     ("g723.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_G723_24, 1, 0.15) ;
317 -*/
318                 test_count++ ;
319                 } ;
320         /* Lite remove end */
321
322         if (do_all || strcmp (argv [1], "caf_ulaw") == 0)
323         {       lcomp_test_short        ("ulaw.caf", SF_FORMAT_CAF | SF_FORMAT_ULAW, 2, 0.04) ;
324                 lcomp_test_int          ("ulaw.caf", SF_FORMAT_CAF | SF_FORMAT_ULAW, 2, 0.04) ;
325                 /* Lite remove start */
326                 lcomp_test_float        ("ulaw.caf", SF_FORMAT_CAF | SF_FORMAT_ULAW, 2, 0.04) ;
327                 lcomp_test_double       ("ulaw.caf", SF_FORMAT_CAF | SF_FORMAT_ULAW, 2, 0.04) ;
328                 /* Lite remove end */
329
330                 read_raw_test ("ulaw.caf", SF_FORMAT_CAF | SF_FORMAT_ULAW, 2) ;
331                 test_count++ ;
332                 } ;
333
334         if (do_all || strcmp (argv [1], "caf_alaw") == 0)
335         {       lcomp_test_short        ("alaw.caf", SF_FORMAT_CAF | SF_FORMAT_ALAW, 2, 0.04) ;
336                 lcomp_test_int          ("alaw.caf", SF_FORMAT_CAF | SF_FORMAT_ALAW, 2, 0.04) ;
337                 /* Lite remove start */
338                 lcomp_test_float        ("alaw.caf", SF_FORMAT_CAF | SF_FORMAT_ALAW, 2, 0.04) ;
339                 lcomp_test_double       ("alaw.caf", SF_FORMAT_CAF | SF_FORMAT_ALAW, 2, 0.04) ;
340                 /* Lite remove end */
341
342                 read_raw_test ("alaw.caf", SF_FORMAT_CAF | SF_FORMAT_ALAW, 2) ;
343                 test_count++ ;
344                 } ;
345
346
347         if (do_all || strcmp (argv [1], "raw_ulaw") == 0)
348         {       lcomp_test_short        ("ulaw.raw", SF_ENDIAN_LITTLE   | SF_FORMAT_RAW | SF_FORMAT_ULAW, 2, 0.04) ;
349                 lcomp_test_int          ("ulaw.raw", SF_ENDIAN_BIG              | SF_FORMAT_RAW | SF_FORMAT_ULAW, 2, 0.04) ;
350                 /* Lite remove start */
351                 lcomp_test_float        ("ulaw.raw", SF_ENDIAN_LITTLE   | SF_FORMAT_RAW | SF_FORMAT_ULAW, 2, 0.04) ;
352                 lcomp_test_double       ("ulaw.raw", SF_ENDIAN_BIG              | SF_FORMAT_RAW | SF_FORMAT_ULAW, 2, 0.04) ;
353                 /* Lite remove end */
354                 test_count++ ;
355                 } ;
356
357         if (do_all || strcmp (argv [1], "raw_alaw") == 0)
358         {       lcomp_test_short        ("alaw.raw", SF_ENDIAN_LITTLE   | SF_FORMAT_RAW | SF_FORMAT_ALAW, 2, 0.04) ;
359                 lcomp_test_int          ("alaw.raw", SF_ENDIAN_BIG              | SF_FORMAT_RAW | SF_FORMAT_ALAW, 2, 0.04) ;
360                 /* Lite remove start */
361                 lcomp_test_float        ("alaw.raw", SF_ENDIAN_LITTLE   | SF_FORMAT_RAW | SF_FORMAT_ALAW, 2, 0.04) ;
362                 lcomp_test_double       ("alaw.raw", SF_ENDIAN_BIG              | SF_FORMAT_RAW | SF_FORMAT_ALAW, 2, 0.04) ;
363                 /* Lite remove end */
364                 test_count++ ;
365                 } ;
366
367         if (do_all || strcmp (argv [1], "raw_gsm610") == 0)
368         {       /* Don't do lcomp_test_XXX as the errors are too big. */
369                 sdlcomp_test_short      ("raw.gsm", SF_FORMAT_RAW | SF_FORMAT_GSM610, 1, 0.24) ;
370                 sdlcomp_test_int        ("raw.gsm", SF_FORMAT_RAW | SF_FORMAT_GSM610, 1, 0.24) ;
371                 sdlcomp_test_float      ("raw.gsm", SF_FORMAT_RAW | SF_FORMAT_GSM610, 1, 0.24) ;
372                 sdlcomp_test_double     ("raw.gsm", SF_FORMAT_RAW | SF_FORMAT_GSM610, 1, 0.24) ;
373                 test_count++ ;
374                 } ;
375
376         if (do_all || strcmp (argv [1], "ogg_vorbis") == 0)
377         {       if (HAVE_EXTERNAL_LIBS)
378                 {       /* Don't do lcomp_test_XXX as the errors are too big. */
379                         sdlcomp_test_short      ("vorbis.oga", SF_FORMAT_OGG | SF_FORMAT_VORBIS, 1, 0.30) ;
380                         sdlcomp_test_int        ("vorbis.oga", SF_FORMAT_OGG | SF_FORMAT_VORBIS, 1, 0.30) ;
381                         sdlcomp_test_float      ("vorbis.oga", SF_FORMAT_OGG | SF_FORMAT_VORBIS, 1, 0.30) ;
382                         sdlcomp_test_double     ("vorbis.oga", SF_FORMAT_OGG | SF_FORMAT_VORBIS, 1, 0.30) ;
383                         }
384                 else
385                         puts ("    No Ogg/Vorbis tests because Ogg/Vorbis support was not compiled in.") ;
386
387                 test_count++ ;
388                 } ;
389
390         /* Lite remove start */
391         if (do_all || strcmp (argv [1], "ircam_ulaw") == 0)
392         {       lcomp_test_short        ("ulaw.ircam", SF_ENDIAN_LITTLE | SF_FORMAT_IRCAM | SF_FORMAT_ULAW, 2, 0.04) ;
393                 lcomp_test_int          ("ulaw.ircam", SF_ENDIAN_BIG    | SF_FORMAT_IRCAM | SF_FORMAT_ULAW, 2, 0.04) ;
394                 lcomp_test_float        ("ulaw.ircam", SF_ENDIAN_LITTLE | SF_FORMAT_IRCAM | SF_FORMAT_ULAW, 2, 0.04) ;
395                 lcomp_test_double       ("ulaw.ircam", SF_ENDIAN_BIG    | SF_FORMAT_IRCAM | SF_FORMAT_ULAW, 2, 0.04) ;
396                 test_count++ ;
397                 } ;
398
399         if (do_all || strcmp (argv [1], "ircam_alaw") == 0)
400         {       lcomp_test_short        ("alaw.ircam", SF_ENDIAN_LITTLE | SF_FORMAT_IRCAM | SF_FORMAT_ALAW, 2, 0.04) ;
401                 lcomp_test_int          ("alaw.ircam", SF_ENDIAN_BIG    | SF_FORMAT_IRCAM | SF_FORMAT_ALAW, 2, 0.04) ;
402                 lcomp_test_float        ("alaw.ircam", SF_ENDIAN_LITTLE | SF_FORMAT_IRCAM | SF_FORMAT_ALAW, 2, 0.04) ;
403                 lcomp_test_double       ("alaw.ircam", SF_ENDIAN_BIG    | SF_FORMAT_IRCAM | SF_FORMAT_ALAW, 2, 0.04) ;
404                 test_count++ ;
405                 } ;
406
407         if (do_all || strcmp (argv [1], "nist_ulaw") == 0)
408         {       lcomp_test_short        ("ulaw.nist", SF_ENDIAN_LITTLE  | SF_FORMAT_NIST | SF_FORMAT_ULAW, 2, 0.04) ;
409                 lcomp_test_int          ("ulaw.nist", SF_ENDIAN_BIG             | SF_FORMAT_NIST | SF_FORMAT_ULAW, 2, 0.04) ;
410                 lcomp_test_float        ("ulaw.nist", SF_ENDIAN_LITTLE  | SF_FORMAT_NIST | SF_FORMAT_ULAW, 2, 0.04) ;
411                 lcomp_test_double       ("ulaw.nist", SF_ENDIAN_BIG             | SF_FORMAT_NIST | SF_FORMAT_ULAW, 2, 0.04) ;
412                 test_count++ ;
413                 } ;
414
415         if (do_all || strcmp (argv [1], "nist_alaw") == 0)
416         {       lcomp_test_short        ("alaw.nist", SF_ENDIAN_LITTLE  | SF_FORMAT_NIST | SF_FORMAT_ALAW, 2, 0.04) ;
417                 lcomp_test_int          ("alaw.nist", SF_ENDIAN_BIG             | SF_FORMAT_NIST | SF_FORMAT_ALAW, 2, 0.04) ;
418                 lcomp_test_float        ("alaw.nist", SF_ENDIAN_LITTLE  | SF_FORMAT_NIST | SF_FORMAT_ALAW, 2, 0.04) ;
419                 lcomp_test_double       ("alaw.nist", SF_ENDIAN_BIG             | SF_FORMAT_NIST | SF_FORMAT_ALAW, 2, 0.04) ;
420                 test_count++ ;
421                 } ;
422
423         if (do_all || strcmp (argv [1], "voc_ulaw") == 0)
424         {       lcomp_test_short        ("ulaw.voc", SF_FORMAT_VOC | SF_FORMAT_ULAW, 2, 0.04) ;
425                 lcomp_test_int          ("ulaw.voc", SF_FORMAT_VOC | SF_FORMAT_ULAW, 2, 0.04) ;
426                 lcomp_test_float        ("ulaw.voc", SF_FORMAT_VOC | SF_FORMAT_ULAW, 2, 0.04) ;
427                 lcomp_test_double       ("ulaw.voc", SF_FORMAT_VOC | SF_FORMAT_ULAW, 2, 0.04) ;
428                 test_count++ ;
429                 } ;
430
431         if (do_all || strcmp (argv [1], "voc_alaw") == 0)
432         {       lcomp_test_short        ("alaw.voc", SF_FORMAT_VOC | SF_FORMAT_ALAW, 2, 0.04) ;
433                 lcomp_test_int          ("alaw.voc", SF_FORMAT_VOC | SF_FORMAT_ALAW, 2, 0.04) ;
434                 lcomp_test_float        ("alaw.voc", SF_FORMAT_VOC | SF_FORMAT_ALAW, 2, 0.04) ;
435                 lcomp_test_double       ("alaw.voc", SF_FORMAT_VOC | SF_FORMAT_ALAW, 2, 0.04) ;
436                 test_count++ ;
437                 } ;
438         /* Lite remove end */
439
440         if (do_all || strcmp (argv [1], "w64_ulaw") == 0)
441         {       lcomp_test_short        ("ulaw.w64", SF_FORMAT_W64 | SF_FORMAT_ULAW, 2, 0.04) ;
442                 lcomp_test_int          ("ulaw.w64", SF_FORMAT_W64 | SF_FORMAT_ULAW, 2, 0.04) ;
443                 /* Lite remove start */
444                 lcomp_test_float        ("ulaw.w64", SF_FORMAT_W64 | SF_FORMAT_ULAW, 2, 0.04) ;
445                 lcomp_test_double       ("ulaw.w64", SF_FORMAT_W64 | SF_FORMAT_ULAW, 2, 0.04) ;
446                 /* Lite remove end */
447
448                 read_raw_test ("ulaw.w64", SF_FORMAT_W64 | SF_FORMAT_ULAW, 2) ;
449                 test_count++ ;
450                 } ;
451
452         if (do_all || strcmp (argv [1], "w64_alaw") == 0)
453         {       lcomp_test_short        ("alaw.w64", SF_FORMAT_W64 | SF_FORMAT_ALAW, 2, 0.04) ;
454                 lcomp_test_int          ("alaw.w64", SF_FORMAT_W64 | SF_FORMAT_ALAW, 2, 0.04) ;
455                 /* Lite remove start */
456                 lcomp_test_float        ("alaw.w64", SF_FORMAT_W64 | SF_FORMAT_ALAW, 2, 0.04) ;
457                 lcomp_test_double       ("alaw.w64", SF_FORMAT_W64 | SF_FORMAT_ALAW, 2, 0.04) ;
458                 /* Lite remove end */
459
460                 read_raw_test ("alaw.w64", SF_FORMAT_W64 | SF_FORMAT_ALAW, 2) ;
461                 test_count++ ;
462                 } ;
463
464         /* Lite remove start */
465         if (do_all || strcmp (argv [1], "w64_ima") == 0)
466         {       lcomp_test_short        ("ima.w64", SF_FORMAT_W64 | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
467                 lcomp_test_int          ("ima.w64", SF_FORMAT_W64 | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
468                 lcomp_test_float        ("ima.w64", SF_FORMAT_W64 | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
469                 lcomp_test_double       ("ima.w64", SF_FORMAT_W64 | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
470
471                 sdlcomp_test_short      ("ima.w64", SF_FORMAT_W64 | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
472                 sdlcomp_test_int        ("ima.w64", SF_FORMAT_W64 | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
473                 sdlcomp_test_float      ("ima.w64", SF_FORMAT_W64 | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
474                 sdlcomp_test_double     ("ima.w64", SF_FORMAT_W64 | SF_FORMAT_IMA_ADPCM, 2, 0.18) ;
475                 test_count++ ;
476                 } ;
477
478         if (do_all || strcmp (argv [1], "w64_msadpcm") == 0)
479         {       lcomp_test_short        ("msadpcm.w64", SF_FORMAT_W64 | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
480                 lcomp_test_int          ("msadpcm.w64", SF_FORMAT_W64 | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
481                 lcomp_test_float        ("msadpcm.w64", SF_FORMAT_W64 | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
482                 lcomp_test_double       ("msadpcm.w64", SF_FORMAT_W64 | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
483
484                 sdlcomp_test_short      ("msadpcm.w64", SF_FORMAT_W64 | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
485                 sdlcomp_test_int        ("msadpcm.w64", SF_FORMAT_W64 | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
486                 sdlcomp_test_float      ("msadpcm.w64", SF_FORMAT_W64 | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
487                 sdlcomp_test_double     ("msadpcm.w64", SF_FORMAT_W64 | SF_FORMAT_MS_ADPCM, 2, 0.36) ;
488                 test_count++ ;
489                 } ;
490
491         if (do_all || strcmp (argv [1], "wve") == 0)
492         {       lcomp_test_short        ("psion.wve", SF_FORMAT_WVE | SF_FORMAT_ALAW, 1, 0.04) ;
493                 lcomp_test_int          ("psion.wve", SF_FORMAT_WVE | SF_FORMAT_ALAW, 1, 0.04) ;
494                 /* Lite remove start */
495                 lcomp_test_float        ("psion.wve", SF_FORMAT_WVE | SF_FORMAT_ALAW, 1, 0.04) ;
496                 lcomp_test_double       ("psion.wve", SF_FORMAT_WVE | SF_FORMAT_ALAW, 1, 0.04) ;
497                 /* Lite remove end */
498                 test_count++ ;
499                 } ;
500
501         /* Lite remove end */
502
503         if (do_all || strcmp (argv [1], "w64_gsm610") == 0)
504         {       /* Don't do lcomp_test_XXX as the errors are too big. */
505                 sdlcomp_test_short      ("gsm610.w64", SF_FORMAT_W64 | SF_FORMAT_GSM610, 1, 0.2) ;
506                 sdlcomp_test_int        ("gsm610.w64", SF_FORMAT_W64 | SF_FORMAT_GSM610, 1, 0.2) ;
507                 /* Lite remove start */
508                 sdlcomp_test_float      ("gsm610.w64", SF_FORMAT_W64 | SF_FORMAT_GSM610, 1, 0.2) ;
509                 sdlcomp_test_double     ("gsm610.w64", SF_FORMAT_W64 | SF_FORMAT_GSM610, 1, 0.2) ;
510                 /* Lite remove end */
511                 test_count++ ;
512                 } ;
513
514         /* Lite remove start */
515         if (do_all || strcmp (argv [1], "vox_adpcm") == 0)
516         {       lcomp_test_short        ("adpcm.vox", SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM, 1, 0.17) ;
517                 lcomp_test_int          ("adpcm.vox", SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM, 1, 0.17) ;
518                 lcomp_test_float        ("adpcm.vox", SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM, 1, 0.17) ;
519                 lcomp_test_double       ("adpcm.vox", SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM, 1, 0.17) ;
520
521                 sdlcomp_test_short      ("adpcm.vox", SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM, 1, 0.072) ;
522                 sdlcomp_test_int        ("adpcm.vox", SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM, 1, 0.072) ;
523                 sdlcomp_test_float      ("adpcm.vox", SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM, 1, 0.072) ;
524                 sdlcomp_test_double     ("adpcm.vox", SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM, 1, 0.072) ;
525                 test_count++ ;
526                 } ;
527
528         if (do_all || strcmp (argv [1], "xi_dpcm") == 0)
529         {       lcomp_test_short        ("8bit.xi", SF_FORMAT_XI | SF_FORMAT_DPCM_8, 1, 0.25) ;
530                 lcomp_test_int          ("8bit.xi", SF_FORMAT_XI | SF_FORMAT_DPCM_8, 1, 0.25) ;
531
532                 lcomp_test_short        ("16bit.xi", SF_FORMAT_XI | SF_FORMAT_DPCM_16, 1, 0.002) ;
533                 lcomp_test_int          ("16bit.xi", SF_FORMAT_XI | SF_FORMAT_DPCM_16, 1, 0.002) ;
534                 lcomp_test_float        ("16bit.xi", SF_FORMAT_XI | SF_FORMAT_DPCM_16, 1, 0.002) ;
535                 lcomp_test_double       ("16bit.xi", SF_FORMAT_XI | SF_FORMAT_DPCM_16, 1, 0.002) ;
536                 test_count++ ;
537                 } ;
538         /* Lite remove end */
539
540         if (test_count == 0)
541         {       printf ("************************************\n") ;
542                 printf ("*  No '%s' test defined.\n", argv [1]) ;
543                 printf ("************************************\n") ;
544                 return 1 ;
545                 } ;
546
547         return 0 ;
548 } /* main */
549
550 /*============================================================================================
551 **      Here are the test functions.
552 */
553
554 static void
555 lcomp_test_short (const char *filename, int filetype, int channels, double margin)
556 {       SNDFILE                 *file ;
557         SF_INFO                 sfinfo ;
558         int                             k, m, seekpos, half_max_abs ;
559         long                    datalen ;
560         short                   *orig, *data ;
561
562         print_test_name ("lcomp_test_short", filename) ;
563
564         datalen = BUFFER_SIZE / channels ;
565
566         data = data_buffer.s ;
567         orig = orig_buffer.s ;
568
569         gen_signal_double (orig_buffer.d, 32000.0, channels, datalen) ;
570         for (k = 0 ; k < channels * datalen ; k++)
571                 orig [k] = (short) (orig_buffer.d [k]) ;
572
573         sfinfo.samplerate       = SAMPLE_RATE ;
574         sfinfo.frames           = 123456789 ;   /* Ridiculous value. */
575         sfinfo.channels         = channels ;
576         sfinfo.format           = filetype ;
577
578         file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
579         test_writef_short_or_die (file, 0, orig, datalen, __LINE__) ;
580         sf_set_string (file, SF_STR_COMMENT, long_comment) ;
581         sf_close (file) ;
582
583         memset (data, 0, datalen * sizeof (short)) ;
584
585         if ((filetype & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
586                 memset (&sfinfo, 0, sizeof (sfinfo)) ;
587
588         file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
589
590         if ((sfinfo.format & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)) != (filetype & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)))
591         {       printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
592                 exit (1) ;
593                 } ;
594
595         if (sfinfo.frames < datalen / channels)
596         {       printf ("Too few frames in file. (%ld should be a little more than %ld)\n", SF_COUNT_TO_LONG (sfinfo.frames), datalen) ;
597                 exit (1) ;
598                 } ;
599
600         if (sfinfo.frames > (datalen + datalen / 20))
601         {       printf ("Too many frames in file. (%ld should be a little more than %ld)\n", SF_COUNT_TO_LONG (sfinfo.frames), datalen) ;
602                 exit (1) ;
603                 } ;
604
605         if (sfinfo.channels != channels)
606         {       printf ("Incorrect number of channels in file.\n") ;
607                 exit (1) ;
608                 } ;
609
610         check_log_buffer_or_die (file, __LINE__) ;
611
612         check_comment (file, filetype, __LINE__) ;
613
614         test_readf_short_or_die (file, 0, data, datalen, __LINE__) ;
615
616         half_max_abs = 0 ;
617         for (k = 0 ; k < datalen ; k++)
618         {       if (error_function (data [k], orig [k], margin))
619                 {       printf ("\n\nLine %d: Incorrect sample A (#%d : %d should be %d).\n", __LINE__, k, data [k], orig [k]) ;
620                         oct_save_short (orig, data, datalen) ;
621                         exit (1) ;
622                         } ;
623                 half_max_abs = LCT_MAX (half_max_abs, abs (data [k] / 2)) ;
624                 } ;
625
626         if (half_max_abs < 1.0)
627         {       printf ("\n\nLine %d: Signal is all zeros.\n", __LINE__) ;
628                 exit (1) ;
629                 } ;
630
631         if ((k = sf_readf_short (file, data, datalen)) != sfinfo.frames - datalen)
632         {       printf ("\n\nLine %d: Incorrect read length (%ld should be %d).\n", __LINE__,
633                         SF_COUNT_TO_LONG (channels * sfinfo.frames - datalen), k) ;
634                 exit (1) ;
635                 } ;
636
637         /*      This check is only for block based encoders which must append silence
638         **      to the end of a file so as to fill out a block.
639         */
640         for (k = 0 ; k < sfinfo.frames - datalen ; k++)
641                 if (abs (data [channels * k]) > decay_response (channels * k))
642                 {       printf ("\n\nLine %d : Incorrect sample B (#%d : abs (%d) should be < %d).\n", __LINE__, channels * k, data [channels * k], decay_response (channels * k)) ;
643                         exit (1) ;
644                         } ;
645
646         if (! sfinfo.seekable)
647         {       sf_close (file) ;
648                 unlink (filename) ;
649                 printf ("ok\n") ;
650                 return ;
651                 } ;
652
653         /* Now test sf_seek function. */
654
655         if ((k = sf_seek (file, 0, SEEK_SET)) != 0)
656         {       printf ("\n\nLine %d: Seek to start of file failed (%d).\n", __LINE__, k) ;
657                 exit (1) ;
658                 } ;
659
660         for (m = 0 ; m < 3 ; m++)
661         {       test_readf_short_or_die (file, m, data, 11, __LINE__) ;
662
663                 for (k = 0 ; k < channels * 11 ; k++)
664                         if (error_function (1.0 * data [k], 1.0 * orig [k + channels * m * 11], margin))
665                         {       printf ("\n\nLine %d: Incorrect sample (m = %d) (#%d : %d => %d).\n", __LINE__, m, k + channels * m * 11, orig [k + channels * m * 11], data [k]) ;
666                                 for (m = 0 ; m < channels ; m++)
667                                         printf ("%d ", data [m]) ;
668                                 printf ("\n") ;
669                                 exit (1) ;
670                                 } ;
671                 } ;
672
673         seekpos = BUFFER_SIZE / 10 ;
674
675         /* Check seek from start of file. */
676         if ((k = sf_seek (file, seekpos, SEEK_SET)) != seekpos)
677         {       printf ("Seek to start of file + %d failed (%d).\n", seekpos, k) ;
678                 exit (1) ;
679                 } ;
680
681         test_readf_short_or_die (file, 0, data, 1, __LINE__) ;
682
683         if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin))
684         {       printf ("\n\nLine %d: sf_seek (SEEK_SET) followed by sf_readf_short failed (%d, %d).\n", __LINE__, orig [1], data [0]) ;
685                 exit (1) ;
686                 } ;
687
688         if ((k = sf_seek (file, 0, SEEK_CUR)) != seekpos + 1)
689         {       printf ("\n\nLine %d: sf_seek (SEEK_CUR) with 0 offset failed (%d should be %d)\n", __LINE__, k, seekpos + 1) ;
690                 exit (1) ;
691                 } ;
692
693         seekpos = sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ;
694         k = sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ;
695         test_readf_short_or_die (file, 0, data, 1, __LINE__) ;
696         if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin) || k != seekpos)
697         {       printf ("\n\nLine %d: sf_seek (forwards, SEEK_CUR) followed by sf_readf_short failed (%d, %d) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos + 1) ;
698                 oct_save_short (orig, data, datalen) ;
699                 exit (1) ;
700                 } ;
701
702         seekpos = sf_seek (file, 0, SEEK_CUR) - 20 ;
703         /* Check seek backward from current position. */
704         k = sf_seek (file, -20, SEEK_CUR) ;
705         test_readf_short_or_die (file, 0, data, 1, __LINE__) ;
706         if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin) || k != seekpos)
707         {       printf ("\nLine %d: sf_seek (backwards, SEEK_CUR) followed by sf_readf_short failed (%d, %d) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos) ;
708                 exit (1) ;
709                 } ;
710
711         /* Check that read past end of file returns number of items. */
712         sf_seek (file, sfinfo.frames, SEEK_SET) ;
713
714         if ((k = sf_readf_short (file, data, datalen)) != 0)
715         {       printf ("\n\nLine %d: Return value from sf_readf_short past end of file incorrect (%d).\n", __LINE__, k) ;
716                 exit (1) ;
717                 } ;
718
719         /* Check seek backward from end. */
720         if ((k = sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5)
721         {       printf ("\n\nLine %d: sf_seek (SEEK_END) returned %d instead of %d.\n", __LINE__, k, 5) ;
722                 exit (1) ;
723                 } ;
724
725         test_readf_short_or_die (file, 0, data, 1, __LINE__) ;
726         if (error_function (1.0 * data [0], 1.0 * orig [5 * channels], margin))
727         {       printf ("\nLine %d: sf_seek (SEEK_END) followed by sf_readf_short failed (%d should be %d).\n", __LINE__, data [0], orig [5 * channels]) ;
728                 exit (1) ;
729                 } ;
730
731         sf_close (file) ;
732
733         unlink (filename) ;
734         printf ("ok\n") ;
735 } /* lcomp_test_short */
736
737 /*--------------------------------------------------------------------------------------------
738 */
739
740 static void
741 lcomp_test_int (const char *filename, int filetype, int channels, double margin)
742 {       SNDFILE                 *file ;
743         SF_INFO                 sfinfo ;
744         int                             k, m, half_max_abs ;
745         long                    datalen, seekpos ;
746         double                  scale, max_val ;
747         int                             *orig, *data ;
748
749         print_test_name ("lcomp_test_int", filename) ;
750
751         datalen = BUFFER_SIZE / channels ;
752
753         if (is_lossy (filetype))
754         {       scale = 1.0 * 0x10000 ;
755                 max_val = 32000.0 * scale ;
756                 }
757         else
758         {       scale = 1.0 ;
759                 max_val = 0x7fffffff * scale ;
760                 } ;
761
762         data = data_buffer.i ;
763         orig = orig_buffer.i ;
764
765         gen_signal_double (orig_buffer.d, max_val, channels, datalen) ;
766
767         for (k = 0 ; k < channels * datalen ; k++)
768                 orig [k] = lrint (orig_buffer.d [k]) ;
769
770         sfinfo.samplerate       = SAMPLE_RATE ;
771         sfinfo.frames           = 123456789 ;   /* Ridiculous value. */
772         sfinfo.channels         = channels ;
773         sfinfo.format           = filetype ;
774
775         file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
776         test_writef_int_or_die (file, 0, orig, datalen, __LINE__) ;
777         sf_set_string (file, SF_STR_COMMENT, long_comment) ;
778         sf_close (file) ;
779
780         memset (data, 0, datalen * sizeof (int)) ;
781
782         if ((filetype & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
783                 memset (&sfinfo, 0, sizeof (sfinfo)) ;
784
785         file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
786
787         if ((sfinfo.format & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)) != (filetype & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)))
788         {       printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
789                 exit (1) ;
790                 } ;
791
792         if (sfinfo.frames < datalen / channels)
793         {       printf ("Too few.frames in file. (%ld should be a little more than %ld)\n", datalen, SF_COUNT_TO_LONG (sfinfo.frames)) ;
794                 exit (1) ;
795                 } ;
796
797         if (sfinfo.frames > (datalen + datalen / 20))
798         {       printf ("Too many.frames in file. (%ld should be a little more than %ld)\n", datalen, SF_COUNT_TO_LONG (sfinfo.frames)) ;
799                 exit (1) ;
800                 } ;
801
802         if (sfinfo.channels != channels)
803         {       printf ("Incorrect number of channels in file.\n") ;
804                 exit (1) ;
805                 } ;
806
807         check_log_buffer_or_die (file, __LINE__) ;
808
809         check_comment (file, filetype, __LINE__) ;
810
811         test_readf_int_or_die (file, 0, data, datalen, __LINE__) ;
812
813         half_max_abs = 0 ;
814         for (k = 0 ; k < datalen ; k++)
815         {       if (error_function (data [k] / scale, orig [k] / scale, margin))
816                 {       printf ("\nLine %d: Incorrect sample (#%d : %f should be %f).\n", __LINE__, k, data [k] / scale, orig [k] / scale) ;
817                         oct_save_int (orig, data, datalen) ;
818                         exit (1) ;
819                         } ;
820                 half_max_abs = LCT_MAX (half_max_abs, abs (data [k] / 2)) ;
821                 } ;
822
823         if (half_max_abs < 1.0)
824         {       printf ("\n\nLine %d: Signal is all zeros (%d, 0x%X).\n", __LINE__, half_max_abs, half_max_abs) ;
825                 exit (1) ;
826                 } ;
827
828         if ((k = sf_readf_int (file, data, datalen)) != sfinfo.frames - datalen)
829         {       printf ("\n\nLine %d: Incorrect read length (%ld should be %d).\n", __LINE__,
830                         SF_COUNT_TO_LONG (channels * sfinfo.frames - datalen), k) ;
831                 exit (1) ;
832                 } ;
833
834         /*      This check is only for block based encoders which must append silence
835         **      to the end of a file so as to fill out a block.
836         */
837         if ((sfinfo.format & SF_FORMAT_SUBMASK) != SF_FORMAT_MS_ADPCM)
838                 for (k = 0 ; k < sfinfo.frames - datalen ; k++)
839                         if (abs (data [channels * k] / scale) > decay_response (channels * k))
840                         {       printf ("\n\nLine %d : Incorrect sample B (#%d : abs (%d) should be < %d).\n", __LINE__, channels * k, data [channels * k], decay_response (channels * k)) ;
841                                 exit (1) ;
842                                 } ;
843
844         if (! sfinfo.seekable)
845         {       sf_close (file) ;
846                 unlink (filename) ;
847                 printf ("ok\n") ;
848                 return ;
849                 } ;
850
851         /* Now test sf_seek function. */
852
853         if ((k = sf_seek (file, 0, SEEK_SET)) != 0)
854         {       printf ("\n\nLine %d: Seek to start of file failed (%d).\n", __LINE__, k) ;
855                 exit (1) ;
856                 } ;
857
858         for (m = 0 ; m < 3 ; m++)
859         {       test_readf_int_or_die (file, m, data, 11, __LINE__) ;
860
861                 for (k = 0 ; k < channels * 11 ; k++)
862                         if (error_function (data [k] / scale, orig [k + channels * m * 11] / scale, margin))
863                         {       printf ("\nLine %d: Incorrect sample (m = %d) (#%d : %d => %d).\n", __LINE__, m, k + channels * m * 11, orig [k + channels * m * 11], data [k]) ;
864                                 for (m = 0 ; m < channels ; m++)
865                                         printf ("%d ", data [m]) ;
866                                 printf ("\n") ;
867                                 exit (1) ;
868                                 } ;
869                 } ;
870
871         seekpos = BUFFER_SIZE / 10 ;
872
873         /* Check seek from start of file. */
874         if ((k = sf_seek (file, seekpos, SEEK_SET)) != seekpos)
875         {       printf ("Seek to start of file + %ld failed (%d).\n", seekpos, k) ;
876                 exit (1) ;
877                 } ;
878
879         test_readf_int_or_die (file, 0, data, 1, __LINE__) ;
880
881         if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin))
882         {       printf ("\nLine %d: sf_seek (SEEK_SET) followed by sf_readf_int failed (%d, %d).\n", __LINE__, orig [1], data [0]) ;
883                 exit (1) ;
884                 } ;
885
886         if ((k = sf_seek (file, 0, SEEK_CUR)) != seekpos + 1)
887         {       printf ("\n\nLine %d: sf_seek (SEEK_CUR) with 0 offset failed (%d should be %ld)\n", __LINE__, k, seekpos + 1) ;
888                 exit (1) ;
889                 } ;
890
891         seekpos = sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ;
892         k = sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ;
893         test_readf_int_or_die (file, 0, data, 1, __LINE__) ;
894         if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin) || k != seekpos)
895         {       printf ("\nLine %d: sf_seek (forwards, SEEK_CUR) followed by sf_readf_int failed (%d, %d) (%d, %ld).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos + 1) ;
896                 exit (1) ;
897                 } ;
898
899         seekpos = sf_seek (file, 0, SEEK_CUR) - 20 ;
900         /* Check seek backward from current position. */
901         k = sf_seek (file, -20, SEEK_CUR) ;
902         test_readf_int_or_die (file, 0, data, 1, __LINE__) ;
903         if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin) || k != seekpos)
904         {       printf ("\nLine %d: sf_seek (backwards, SEEK_CUR) followed by sf_readf_int failed (%d, %d) (%d, %ld).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos) ;
905                 exit (1) ;
906                 } ;
907
908         /* Check that read past end of file returns number of items. */
909         sf_seek (file, sfinfo.frames, SEEK_SET) ;
910
911         if ((k = sf_readf_int (file, data, datalen)) != 0)
912         {       printf ("\n\nLine %d: Return value from sf_readf_int past end of file incorrect (%d).\n", __LINE__, k) ;
913                 exit (1) ;
914                 } ;
915
916         /* Check seek backward from end. */
917         if ((k = sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5)
918         {       printf ("\n\nLine %d: sf_seek (SEEK_END) returned %d instead of %d.\n", __LINE__, k, 5) ;
919                 exit (1) ;
920                 } ;
921
922         test_readf_int_or_die (file, 0, data, 1, __LINE__) ;
923         if (error_function (data [0] / scale, orig [5 * channels] / scale, margin))
924         {       printf ("\nLine %d: sf_seek (SEEK_END) followed by sf_readf_short failed (%d should be %d).\n", __LINE__, data [0], orig [5]) ;
925                 exit (1) ;
926                 } ;
927
928         sf_close (file) ;
929
930         unlink (filename) ;
931         printf ("ok\n") ;
932 } /* lcomp_test_int */
933
934 /*--------------------------------------------------------------------------------------------
935 */
936
937 static void
938 lcomp_test_float (const char *filename, int filetype, int channels, double margin)
939 {       SNDFILE                 *file ;
940         SF_INFO                 sfinfo ;
941         int                             k, m, seekpos ;
942         long                    datalen ;
943         float                   *orig, *data ;
944         double                  half_max_abs ;
945
946         print_test_name ("lcomp_test_float", filename) ;
947
948         datalen = BUFFER_SIZE / channels ;
949
950         data = data_buffer.f ;
951         orig = orig_buffer.f ;
952
953         gen_signal_double (orig_buffer.d, 32000.0, channels, datalen) ;
954         for (k = 0 ; k < channels * datalen ; k++)
955                 orig [k] = orig_buffer.d [k] ;
956
957         sfinfo.samplerate       = SAMPLE_RATE ;
958         sfinfo.frames           = 123456789 ;   /* Ridiculous value. */
959         sfinfo.channels         = channels ;
960         sfinfo.format           = filetype ;
961
962         file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
963         sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
964         test_writef_float_or_die (file, 0, orig, datalen, __LINE__) ;
965         sf_set_string (file, SF_STR_COMMENT, long_comment) ;
966         sf_close (file) ;
967
968         memset (data, 0, datalen * sizeof (float)) ;
969
970         if ((filetype & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
971                 memset (&sfinfo, 0, sizeof (sfinfo)) ;
972
973         file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
974
975         if ((sfinfo.format & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)) != (filetype & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)))
976         {       printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
977                 exit (1) ;
978                 } ;
979
980         if (sfinfo.frames < datalen / channels)
981         {       printf ("Too few.frames in file. (%ld should be a little more than %ld)\n", datalen, SF_COUNT_TO_LONG (sfinfo.frames)) ;
982                 exit (1) ;
983                 } ;
984
985         if (sfinfo.frames > (datalen + datalen / 20))
986         {       printf ("Too many.frames in file. (%ld should be a little more than %ld)\n", datalen, SF_COUNT_TO_LONG (sfinfo.frames)) ;
987                 exit (1) ;
988                 } ;
989
990         if (sfinfo.channels != channels)
991         {       printf ("Incorrect number of channels in file.\n") ;
992                 exit (1) ;
993                 } ;
994
995         check_comment (file, filetype, __LINE__) ;
996
997         sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
998
999         check_log_buffer_or_die (file, __LINE__) ;
1000
1001         check_comment (file, filetype, __LINE__) ;
1002
1003         sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
1004
1005         test_readf_float_or_die (file, 0, data, datalen, __LINE__) ;
1006
1007         half_max_abs = 0.0 ;
1008         for (k = 0 ; k < datalen ; k++)
1009         {       if (error_function (data [k], orig [k], margin))
1010                 {       printf ("\nLine %d: Incorrect sample A (#%d : %f should be %f).\n", __LINE__, k, data [k], orig [k]) ;
1011                         oct_save_float (orig, data, datalen) ;
1012                         exit (1) ;
1013                         } ;
1014                 half_max_abs = LCT_MAX (half_max_abs, fabs (0.5 * data [k])) ;
1015                 } ;
1016
1017         if (half_max_abs < 1.0)
1018         {       printf ("\n\nLine %d: Signal is all zeros.\n", __LINE__) ;
1019                 exit (1) ;
1020                 } ;
1021
1022         if ((k = sf_readf_float (file, data, datalen)) != sfinfo.frames - datalen)
1023         {       printf ("\n\nLine %d: Incorrect read length (%ld should be %d).\n", __LINE__,
1024                         SF_COUNT_TO_LONG (channels * sfinfo.frames - datalen), k) ;
1025                 exit (1) ;
1026                 } ;
1027
1028         /*      This check is only for block based encoders which must append silence
1029         **      to the end of a file so as to fill out a block.
1030         */
1031         if ((sfinfo.format & SF_FORMAT_SUBMASK) != SF_FORMAT_MS_ADPCM)
1032                 for (k = 0 ; k < sfinfo.frames - datalen ; k++)
1033                         if (abs (data [channels * k]) > decay_response (channels * k))
1034                         {       printf ("\n\nLine %d : Incorrect sample B (#%d : abs (%f) should be < %d).\n", __LINE__, channels * k, data [channels * k], decay_response (channels * k)) ;
1035                                 exit (1) ;
1036                                 } ;
1037
1038         if (! sfinfo.seekable)
1039         {       sf_close (file) ;
1040                 unlink (filename) ;
1041                 printf ("ok\n") ;
1042                 return ;
1043                 } ;
1044
1045         /* Now test sf_seek function. */
1046
1047         if ((k = sf_seek (file, 0, SEEK_SET)) != 0)
1048         {       printf ("\n\nLine %d: Seek to start of file failed (%d).\n", __LINE__, k) ;
1049                 exit (1) ;
1050                 } ;
1051
1052         for (m = 0 ; m < 3 ; m++)
1053         {       test_readf_float_or_die (file, 0, data, 11, __LINE__) ;
1054
1055                 for (k = 0 ; k < channels * 11 ; k++)
1056                         if (error_function (data [k], orig [k + channels * m * 11], margin))
1057                         {       printf ("\nLine %d: Incorrect sample (m = %d) (#%d : %f => %f).\n", __LINE__, m, k + channels * m * 11, orig [k + channels * m * 11], data [k]) ;
1058                                 for (m = 0 ; m < channels ; m++)
1059                                         printf ("%f ", data [m]) ;
1060                                 printf ("\n") ;
1061                                 exit (1) ;
1062                                 } ;
1063                 } ;
1064
1065         seekpos = BUFFER_SIZE / 10 ;
1066
1067         /* Check seek from start of file. */
1068         if ((k = sf_seek (file, seekpos, SEEK_SET)) != seekpos)
1069         {       printf ("Seek to start of file + %d failed (%d).\n", seekpos, k) ;
1070                 exit (1) ;
1071                 } ;
1072
1073         test_readf_float_or_die (file, 0, data, 1, __LINE__) ;
1074
1075         if (error_function (data [0], orig [seekpos * channels], margin))
1076         {       printf ("\nLine %d: sf_seek (SEEK_SET) followed by sf_readf_float failed (%f, %f).\n", __LINE__, orig [1], data [0]) ;
1077                 exit (1) ;
1078                 } ;
1079
1080         if ((k = sf_seek (file, 0, SEEK_CUR)) != seekpos + 1)
1081         {       printf ("\n\nLine %d: sf_seek (SEEK_CUR) with 0 offset failed (%d should be %d)\n", __LINE__, k, seekpos + 1) ;
1082                 exit (1) ;
1083                 } ;
1084
1085         seekpos = sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ;
1086         k = sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ;
1087         test_readf_float_or_die (file, 0, data, 1, __LINE__) ;
1088         if (error_function (data [0], orig [seekpos * channels], margin) || k != seekpos)
1089         {       printf ("\nLine %d: sf_seek (forwards, SEEK_CUR) followed by sf_readf_float failed (%f, %f) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos + 1) ;
1090                 exit (1) ;
1091                 } ;
1092
1093         seekpos = sf_seek (file, 0, SEEK_CUR) - 20 ;
1094         /* Check seek backward from current position. */
1095         k = sf_seek (file, -20, SEEK_CUR) ;
1096         test_readf_float_or_die (file, 0, data, 1, __LINE__) ;
1097         if (error_function (data [0], orig [seekpos * channels], margin) || k != seekpos)
1098         {       printf ("\nLine %d: sf_seek (backwards, SEEK_CUR) followed by sf_readf_float failed (%f, %f) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos) ;
1099                 exit (1) ;
1100                 } ;
1101
1102         /* Check that read past end of file returns number of items. */
1103         sf_seek (file, sfinfo.frames, SEEK_SET) ;
1104
1105         if ((k = sf_readf_float (file, data, datalen)) != 0)
1106         {       printf ("\n\nLine %d: Return value from sf_readf_float past end of file incorrect (%d).\n", __LINE__, k) ;
1107                 exit (1) ;
1108                 } ;
1109
1110         /* Check seek backward from end. */
1111         if ((k = sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5)
1112         {       printf ("\n\nLine %d: sf_seek (SEEK_END) returned %d instead of %d.\n", __LINE__, k, 5) ;
1113                 exit (1) ;
1114                 } ;
1115
1116         test_readf_float_or_die (file, 0, data, 1, __LINE__) ;
1117         if (error_function (data [0], orig [5 * channels], margin))
1118         {       printf ("\nLine %d: sf_seek (SEEK_END) followed by sf_readf_short failed (%f should be %f).\n", __LINE__, data [0], orig [5 * channels]) ;
1119                 exit (1) ;
1120                 } ;
1121
1122         sf_close (file) ;
1123
1124         unlink (filename) ;
1125         printf ("ok\n") ;
1126 } /* lcomp_test_float */
1127
1128 /*--------------------------------------------------------------------------------------------
1129 */
1130
1131 static void
1132 lcomp_test_double (const char *filename, int filetype, int channels, double margin)
1133 {       SNDFILE                 *file ;
1134         SF_INFO                 sfinfo ;
1135         int                             k, m, seekpos ;
1136         long                    datalen ;
1137         double                  *orig, *data ;
1138         double                  half_max_abs ;
1139
1140         print_test_name ("lcomp_test_double", filename) ;
1141
1142         datalen = BUFFER_SIZE / channels ;
1143
1144         data = data_buffer.d ;
1145         orig = orig_buffer.d ;
1146
1147         gen_signal_double (orig_buffer.d, 32000.0, channels, datalen) ;
1148         for (k = 0 ; k < channels * datalen ; k++)
1149                 orig [k] = orig_buffer.d [k] ;
1150
1151         sfinfo.samplerate       = SAMPLE_RATE ;
1152         sfinfo.frames           = 123456789 ;   /* Ridiculous value. */
1153         sfinfo.channels         = channels ;
1154         sfinfo.format           = filetype ;
1155
1156         file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
1157         sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
1158         test_writef_double_or_die (file, 0, orig, datalen, __LINE__) ;
1159         sf_set_string (file, SF_STR_COMMENT, long_comment) ;
1160         sf_close (file) ;
1161
1162         memset (data, 0, datalen * sizeof (double)) ;
1163
1164         if ((filetype & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
1165                 memset (&sfinfo, 0, sizeof (sfinfo)) ;
1166
1167         file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
1168
1169         if ((sfinfo.format & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)) != (filetype & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)))
1170         {       printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
1171                 exit (1) ;
1172                 } ;
1173
1174         if (sfinfo.frames < datalen / channels)
1175         {       printf ("Too few.frames in file. (%ld should be a little more than %ld)\n", datalen, SF_COUNT_TO_LONG (sfinfo.frames)) ;
1176                 exit (1) ;
1177                 } ;
1178
1179         if (sfinfo.frames > (datalen + datalen / 20))
1180         {       printf ("Too many.frames in file. (%ld should be a little more than %ld)\n", datalen, SF_COUNT_TO_LONG (sfinfo.frames)) ;
1181                 exit (1) ;
1182                 } ;
1183
1184         if (sfinfo.channels != channels)
1185         {       printf ("Incorrect number of channels in file.\n") ;
1186                 exit (1) ;
1187                 } ;
1188
1189         check_comment (file, filetype, __LINE__) ;
1190
1191         sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
1192
1193         check_log_buffer_or_die (file, __LINE__) ;
1194
1195         check_comment (file, filetype, __LINE__) ;
1196
1197         sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
1198
1199         test_readf_double_or_die (file, 0, data, datalen, __LINE__) ;
1200
1201         half_max_abs = 0.0 ;
1202         for (k = 0 ; k < datalen ; k++)
1203         {       if (error_function (data [k], orig [k], margin))
1204                 {       printf ("\nLine %d: Incorrect sample A (#%d : %f should be %f).\n", __LINE__, k, data [k], orig [k]) ;
1205                         oct_save_double (orig, data, datalen) ;
1206                         exit (1) ;
1207                         } ;
1208                 half_max_abs = LCT_MAX (half_max_abs, abs (0.5 * data [k])) ;
1209                 } ;
1210
1211         if (half_max_abs < 1.0)
1212         {       printf ("\n\nLine %d: Signal is all zeros.\n", __LINE__) ;
1213                 exit (1) ;
1214                 } ;
1215
1216         if ((k = sf_readf_double (file, data, datalen)) != sfinfo.frames - datalen)
1217         {       printf ("\n\nLine %d: Incorrect read length (%ld should be %d).\n", __LINE__,
1218                         SF_COUNT_TO_LONG (channels * sfinfo.frames - datalen), k) ;
1219                 exit (1) ;
1220                 } ;
1221
1222         /*      This check is only for block based encoders which must append silence
1223         **      to the end of a file so as to fill out a block.
1224         */
1225         if ((sfinfo.format & SF_FORMAT_SUBMASK) != SF_FORMAT_MS_ADPCM)
1226                 for (k = 0 ; k < sfinfo.frames - datalen ; k++)
1227                         if (abs (data [channels * k]) > decay_response (channels * k))
1228                         {       printf ("\n\nLine %d : Incorrect sample B (#%d : abs (%f) should be < %d).\n", __LINE__, channels * k, data [channels * k], decay_response (channels * k)) ;
1229                                 exit (1) ;
1230                                 } ;
1231
1232         if (! sfinfo.seekable)
1233         {       sf_close (file) ;
1234                 unlink (filename) ;
1235                 printf ("ok\n") ;
1236                 return ;
1237                 } ;
1238
1239         /* Now test sf_seek function. */
1240
1241         if ((k = sf_seek (file, 0, SEEK_SET)) != 0)
1242         {       printf ("\n\nLine %d: Seek to start of file failed (%d).\n", __LINE__, k) ;
1243                 exit (1) ;
1244                 } ;
1245
1246         for (m = 0 ; m < 3 ; m++)
1247         {       test_readf_double_or_die (file, m, data, 11, __LINE__) ;
1248
1249                 for (k = 0 ; k < channels * 11 ; k++)
1250                         if (error_function (data [k], orig [k + channels * m * 11], margin))
1251                         {       printf ("\nLine %d: Incorrect sample (m = %d) (#%d : %f => %f).\n", __LINE__, m, k + channels * m * 11, orig [k + channels * m * 11], data [k]) ;
1252                                 for (m = 0 ; m < channels ; m++)
1253                                         printf ("%f ", data [m]) ;
1254                                 printf ("\n") ;
1255                                 exit (1) ;
1256                                 } ;
1257                 } ;
1258
1259         seekpos = BUFFER_SIZE / 10 ;
1260
1261         /* Check seek from start of file. */
1262         if ((k = sf_seek (file, seekpos, SEEK_SET)) != seekpos)
1263         {       printf ("Seek to start of file + %d failed (%d).\n", seekpos, k) ;
1264                 exit (1) ;
1265                 } ;
1266
1267         test_readf_double_or_die (file, 0, data, 1, __LINE__) ;
1268
1269         if (error_function (data [0], orig [seekpos * channels], margin))
1270         {       printf ("\nLine %d: sf_seek (SEEK_SET) followed by sf_readf_double failed (%f, %f).\n", __LINE__, orig [1], data [0]) ;
1271                 exit (1) ;
1272                 } ;
1273
1274         if ((k = sf_seek (file, 0, SEEK_CUR)) != seekpos + 1)
1275         {       printf ("\n\nLine %d: sf_seek (SEEK_CUR) with 0 offset failed (%d should be %d)\n", __LINE__, k, seekpos + 1) ;
1276                 exit (1) ;
1277                 } ;
1278
1279         seekpos = sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ;
1280         k = sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ;
1281         test_readf_double_or_die (file, 0, data, 1, __LINE__) ;
1282         if (error_function (data [0], orig [seekpos * channels], margin) || k != seekpos)
1283         {       printf ("\nLine %d: sf_seek (forwards, SEEK_CUR) followed by sf_readf_double failed (%f, %f) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos + 1) ;
1284                 exit (1) ;
1285                 } ;
1286
1287         seekpos = sf_seek (file, 0, SEEK_CUR) - 20 ;
1288         /* Check seek backward from current position. */
1289         k = sf_seek (file, -20, SEEK_CUR) ;
1290         test_readf_double_or_die (file, 0, data, 1, __LINE__) ;
1291         if (error_function (data [0], orig [seekpos * channels], margin) || k != seekpos)
1292         {       printf ("\nLine %d: sf_seek (backwards, SEEK_CUR) followed by sf_readf_double failed (%f, %f) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos) ;
1293                 exit (1) ;
1294                 } ;
1295
1296         /* Check that read past end of file returns number of items. */
1297         sf_seek (file, sfinfo.frames, SEEK_SET) ;
1298
1299         if ((k = sf_readf_double (file, data, datalen)) != 0)
1300         {       printf ("\n\nLine %d: Return value from sf_readf_double past end of file incorrect (%d).\n", __LINE__, k) ;
1301                 exit (1) ;
1302                 } ;
1303
1304         /* Check seek backward from end. */
1305         if ((k = sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5)
1306         {       printf ("\n\nLine %d: sf_seek (SEEK_END) returned %d instead of %d.\n", __LINE__, k, 5) ;
1307                 exit (1) ;
1308                 } ;
1309
1310         test_readf_double_or_die (file, 0, data, 1, __LINE__) ;
1311         if (error_function (data [0], orig [5 * channels], margin))
1312         {       printf ("\nLine %d: sf_seek (SEEK_END) followed by sf_readf_short failed (%f should be %f).\n", __LINE__, data [0], orig [5 * channels]) ;
1313                 exit (1) ;
1314                 } ;
1315
1316         sf_close (file) ;
1317
1318         unlink (filename) ;
1319         printf ("ok\n") ;
1320 } /* lcomp_test_double */
1321
1322 /*========================================================================================
1323 **      Smoothed differential loss compression tests.
1324 */
1325
1326 static void
1327 sdlcomp_test_short      (const char *filename, int filetype, int channels, double margin)
1328 {       SNDFILE                 *file ;
1329         SF_INFO                 sfinfo ;
1330         int                             k, m, seekpos, half_max_abs ;
1331         long                    datalen ;
1332         short                   *orig, *data, *smooth ;
1333
1334 channels = 1 ;
1335         print_test_name ("sdlcomp_test_short", filename) ;
1336
1337         datalen = BUFFER_SIZE ;
1338
1339         orig = orig_buffer.s ;
1340         data = data_buffer.s ;
1341         smooth = smooth_buffer.s ;
1342
1343         gen_signal_double (orig_buffer.d, 32000.0, channels, datalen) ;
1344         for (k = 0 ; k < datalen ; k++)
1345                 orig [k] = lrint (orig_buffer.d [k]) ;
1346
1347         sfinfo.samplerate       = SAMPLE_RATE ;
1348         sfinfo.frames           = 123456789 ;   /* Ridiculous value. */
1349         sfinfo.channels         = channels ;
1350         sfinfo.format           = filetype ;
1351
1352         /*      The Vorbis encoder has a bug on PowerPC and X86-64 with sample rates
1353         **      <= 22050. Increasing the sample rate to 32000 avoids triggering it.
1354         **      See https://trac.xiph.org/ticket/1229
1355         */
1356         if ((file = sf_open (filename, SFM_WRITE, &sfinfo)) == NULL)
1357         {       const char * errstr ;
1358
1359                 errstr = sf_strerror (NULL) ;
1360                 if (strstr (errstr, "Sample rate chosen is known to trigger a Vorbis") == NULL)
1361                 {       printf ("Line %d: sf_open_fd (SFM_WRITE) failed : %s\n", __LINE__, errstr) ;
1362                         dump_log_buffer (NULL) ;
1363                         exit (1) ;
1364                         } ;
1365
1366                 printf ("\n                                  Sample rate -> 32kHz    ") ;
1367                 sfinfo.samplerate = 32000 ;
1368
1369                 file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
1370                 } ;
1371
1372         test_write_short_or_die (file, 0, orig, datalen, __LINE__) ;
1373         sf_set_string (file, SF_STR_COMMENT, long_comment) ;
1374         sf_close (file) ;
1375
1376         memset (data, 0, datalen * sizeof (short)) ;
1377
1378         if ((filetype & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
1379                 memset (&sfinfo, 0, sizeof (sfinfo)) ;
1380
1381         file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
1382
1383         if (sfinfo.format != filetype)
1384         {       printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
1385                 exit (1) ;
1386                 } ;
1387
1388         if (sfinfo.frames < datalen / channels)
1389         {       printf ("Too few.frames in file. (%ld should be a little more than %ld)\n", datalen, SF_COUNT_TO_LONG (sfinfo.frames)) ;
1390                 exit (1) ;
1391                 } ;
1392
1393         if (sfinfo.frames > (datalen + 400))
1394         {       printf ("Too many.frames in file. (%ld should be a little more than %ld)\n", SF_COUNT_TO_LONG (sfinfo.frames), datalen) ;
1395                 exit (1) ;
1396                 } ;
1397
1398         if (sfinfo.channels != channels)
1399         {       printf ("Incorrect number of channels in file.\n") ;
1400                 exit (1) ;
1401                 } ;
1402
1403         check_comment (file, filetype, __LINE__) ;
1404
1405         sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
1406
1407         check_log_buffer_or_die (file, __LINE__) ;
1408
1409         test_readf_short_or_die (file, 0, data, datalen, __LINE__) ;
1410
1411         memcpy (smooth, orig, datalen * sizeof (short)) ;
1412         smoothed_diff_short (data, datalen) ;
1413         smoothed_diff_short (smooth, datalen) ;
1414
1415         half_max_abs = 0.0 ;
1416         for (k = 0 ; k < datalen ; k++)
1417         {       if (error_function (1.0 * data [k], 1.0 * smooth [k], margin))
1418                 {       printf ("\nLine %d: Incorrect sample (#%d : %d should be %d).\n", __LINE__, k, data [k], smooth [k]) ;
1419                         oct_save_short (orig, smooth, datalen) ;
1420                         exit (1) ;
1421                         } ;
1422                 half_max_abs = LCT_MAX (half_max_abs, abs (0.5 * data [k])) ;
1423                 } ;
1424
1425         if (half_max_abs < 1)
1426         {       printf ("\n\nLine %d: Signal is all zeros.\n", __LINE__) ;
1427                 exit (1) ;
1428                 } ;
1429
1430         if ((k = sf_read_short (file, data, datalen)) != sfinfo.frames - datalen)
1431         {       printf ("\n\nLine %d: Incorrect read length (%d should be %ld).\n", __LINE__, k, SF_COUNT_TO_LONG (sfinfo.frames - datalen)) ;
1432                 exit (1) ;
1433                 } ;
1434
1435         if ((sfinfo.format & SF_FORMAT_SUBMASK) != SF_FORMAT_MS_ADPCM &&
1436                 (sfinfo.format & SF_FORMAT_SUBMASK) != SF_FORMAT_GSM610)
1437                 for (k = 0 ; k < sfinfo.frames - datalen ; k++)
1438                         if (abs (data [k]) > decay_response (k))
1439                         {       printf ("\n\nLine %d: Incorrect sample (#%ld : abs (%d) should be < %d).\n", __LINE__, datalen + k, data [k], decay_response (k)) ;
1440                                 exit (1) ;
1441                                 } ;
1442
1443         /* Now test sf_seek function. */
1444         if (sfinfo.seekable)
1445         {       if ((k = sf_seek (file, 0, SEEK_SET)) != 0)
1446                 {       printf ("\n\nLine %d: Seek to start of file failed (%d).\n", __LINE__, k) ;
1447                         exit (1) ;
1448                         } ;
1449
1450                 for (m = 0 ; m < 3 ; m++)
1451                 {       test_readf_short_or_die (file, m, data, datalen / 7, __LINE__) ;
1452
1453                         smoothed_diff_short (data, datalen / 7) ;
1454                         memcpy (smooth, orig + m * datalen / 7, datalen / 7 * sizeof (short)) ;
1455                         smoothed_diff_short (smooth, datalen / 7) ;
1456
1457                         for (k = 0 ; k < datalen / 7 ; k++)
1458                                 if (error_function (1.0 * data [k], 1.0 * smooth [k], margin))
1459                                 {       printf ("\nLine %d: Incorrect sample C (#%d (%ld) : %d => %d).\n", __LINE__, k, k + m * (datalen / 7), smooth [k], data [k]) ;
1460                                         for (m = 0 ; m < 10 ; m++)
1461                                                 printf ("%d ", data [k]) ;
1462                                         printf ("\n") ;
1463                                         exit (1) ;
1464                                         } ;
1465                         } ; /* for (m = 0 ; m < 3 ; m++) */
1466
1467                 seekpos = BUFFER_SIZE / 10 ;
1468
1469                 /* Check seek from start of file. */
1470                 if ((k = sf_seek (file, seekpos, SEEK_SET)) != seekpos)
1471                 {       printf ("Seek to start of file + %d failed (%d).\n", seekpos, k) ;
1472                         exit (1) ;
1473                         } ;
1474                 test_readf_short_or_die (file, 0, data, 1, __LINE__) ;
1475
1476                 if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin))
1477                 {       printf ("\nLine %d: sf_seek (SEEK_SET) followed by sf_read_short failed (%d, %d).\n", __LINE__, orig [1], data [0]) ;
1478                         exit (1) ;
1479                         } ;
1480
1481                 if ((k = sf_seek (file, 0, SEEK_CUR)) != seekpos + 1)
1482                 {       printf ("\n\nLine %d: sf_seek (SEEK_CUR) with 0 offset failed (%d should be %d)\n", __LINE__, k, seekpos + 1) ;
1483                         exit (1) ;
1484                         } ;
1485
1486                 seekpos = sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ;
1487                 k = sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ;
1488                 test_readf_short_or_die (file, 0, data, 1, __LINE__) ;
1489                 if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin) || k != seekpos)
1490                 {       printf ("\nLine %d: sf_seek (forwards, SEEK_CUR) followed by sf_read_short failed (%d, %d) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos + 1) ;
1491                         exit (1) ;
1492                         } ;
1493
1494                 seekpos = sf_seek (file, 0, SEEK_CUR) - 20 ;
1495                 /* Check seek backward from current position. */
1496                 k = sf_seek (file, -20, SEEK_CUR) ;
1497                 test_readf_short_or_die (file, 0, data, 1, __LINE__) ;
1498                 if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin) || k != seekpos)
1499                 {       printf ("\nLine %d: sf_seek (backwards, SEEK_CUR) followed by sf_read_short failed (%d, %d) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos) ;
1500                         exit (1) ;
1501                         } ;
1502
1503                 /* Check that read past end of file returns number of items. */
1504                 sf_seek (file, sfinfo.frames, SEEK_SET) ;
1505
1506                 if ((k = sf_read_short (file, data, datalen)) != 0)
1507                 {       printf ("\n\nLine %d: Return value from sf_read_short past end of file incorrect (%d).\n", __LINE__, k) ;
1508                         exit (1) ;
1509                         } ;
1510
1511                 /* Check seek backward from end. */
1512
1513                 if ((k = sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5)
1514                 {       printf ("\n\nLine %d: sf_seek (SEEK_END) returned %d instead of %d.\n", __LINE__, k, 5) ;
1515                         exit (1) ;
1516                         } ;
1517
1518                 test_read_short_or_die (file, 0, data, channels, __LINE__) ;
1519                 if (error_function (1.0 * data [0], 1.0 * orig [5 * channels], margin))
1520                 {       printf ("\nLine %d: sf_seek (SEEK_END) followed by sf_read_short failed (%d should be %d).\n", __LINE__, data [0], orig [5 * channels]) ;
1521                         exit (1) ;
1522                         } ;
1523                 } /* if (sfinfo.seekable) */
1524
1525         sf_close (file) ;
1526
1527         unlink (filename) ;
1528         printf ("ok\n") ;
1529 } /* sdlcomp_test_short */
1530
1531 static  void
1532 sdlcomp_test_int        (const char *filename, int filetype, int channels, double margin)
1533 {       SNDFILE                 *file ;
1534         SF_INFO                 sfinfo ;
1535         int                             k, m, seekpos, half_max_abs ;
1536         long                    datalen ;
1537         int                             *orig, *data, *smooth ;
1538         double                  scale ;
1539
1540 channels = 1 ;
1541
1542         print_test_name ("sdlcomp_test_int", filename) ;
1543
1544         datalen = BUFFER_SIZE ;
1545         scale = 1.0 * 0x10000 ;
1546
1547         orig = orig_buffer.i ;
1548         data = data_buffer.i ;
1549         smooth = smooth_buffer.i ;
1550
1551         gen_signal_double (orig_buffer.d, 32000.0 * scale, channels, datalen) ;
1552         for (k = 0 ; k < datalen ; k++)
1553                 orig [k] = lrint (orig_buffer.d [k]) ;
1554
1555         sfinfo.samplerate       = SAMPLE_RATE ;
1556         sfinfo.frames           = 123456789 ;   /* Ridiculous value. */
1557         sfinfo.channels         = channels ;
1558         sfinfo.format           = filetype ;
1559
1560         /*      The Vorbis encoder has a bug on PowerPC and X86-64 with sample rates
1561         **      <= 22050. Increasing the sample rate to 32000 avoids triggering it.
1562         **      See https://trac.xiph.org/ticket/1229
1563         */
1564         if ((file = sf_open (filename, SFM_WRITE, &sfinfo)) == NULL)
1565         {       const char * errstr ;
1566
1567                 errstr = sf_strerror (NULL) ;
1568                 if (strstr (errstr, "Sample rate chosen is known to trigger a Vorbis") == NULL)
1569                 {       printf ("Line %d: sf_open_fd (SFM_WRITE) failed : %s\n", __LINE__, errstr) ;
1570                         dump_log_buffer (NULL) ;
1571                         exit (1) ;
1572                         } ;
1573
1574                 printf ("\n                                  Sample rate -> 32kHz    ") ;
1575                 sfinfo.samplerate = 32000 ;
1576
1577                 file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
1578                 } ;
1579
1580         test_writef_int_or_die (file, 0, orig, datalen, __LINE__) ;
1581         sf_set_string (file, SF_STR_COMMENT, long_comment) ;
1582         sf_close (file) ;
1583
1584         memset (data, 0, datalen * sizeof (int)) ;
1585
1586         if ((filetype & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
1587                 memset (&sfinfo, 0, sizeof (sfinfo)) ;
1588
1589         file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
1590
1591         if (sfinfo.format != filetype)
1592         {       printf ("Returned format incorrect (0x%08X => 0x%08X).\n", filetype, sfinfo.format) ;
1593                 exit (1) ;
1594                 } ;
1595
1596         if (sfinfo.frames < datalen / channels)
1597         {       printf ("Too few.frames in file. (%ld should be a little more than %ld)\n", datalen, SF_COUNT_TO_LONG (sfinfo.frames)) ;
1598                 exit (1) ;
1599                 } ;
1600
1601         if (sfinfo.frames > (datalen + 400))
1602         {       printf ("Too many.frames in file. (%ld should be a little more than %ld)\n", SF_COUNT_TO_LONG (sfinfo.frames), datalen) ;
1603                 exit (1) ;
1604                 } ;
1605
1606         if (sfinfo.channels != channels)
1607         {       printf ("Incorrect number of channels in file.\n") ;
1608                 exit (1) ;
1609                 } ;
1610
1611         check_log_buffer_or_die (file, __LINE__) ;
1612
1613         test_readf_int_or_die (file, 0, data, datalen, __LINE__) ;
1614
1615         memcpy (smooth, orig, datalen * sizeof (int)) ;
1616         smoothed_diff_int (data, datalen) ;
1617         smoothed_diff_int (smooth, datalen) ;
1618
1619         half_max_abs = abs (data [0] >> 16) ;
1620         for (k = 1 ; k < datalen ; k++)
1621         {       if (error_function (data [k] / scale, smooth [k] / scale, margin))
1622                 {       printf ("\nLine %d: Incorrect sample (#%d : %d should be %d).\n", __LINE__, k, data [k], smooth [k]) ;
1623                         oct_save_int (orig, smooth, datalen) ;
1624                         exit (1) ;
1625                         } ;
1626                 half_max_abs = LCT_MAX (half_max_abs, abs (data [k] / 2)) ;
1627                 } ;
1628
1629         if (half_max_abs < 1)
1630         {       printf ("\n\nLine %d: Signal is all zeros.\n", __LINE__) ;
1631                 exit (1) ;
1632                 } ;
1633
1634         if ((k = sf_readf_int (file, data, datalen)) != sfinfo.frames - datalen)
1635         {       printf ("\n\nLine %d: Incorrect read length (%d should be %ld).\n", __LINE__, k, SF_COUNT_TO_LONG (sfinfo.frames - datalen)) ;
1636                 exit (1) ;
1637                 } ;
1638
1639         if ((sfinfo.format & SF_FORMAT_SUBMASK) != SF_FORMAT_IMA_ADPCM &&
1640                 (sfinfo.format & SF_FORMAT_SUBMASK) != SF_FORMAT_MS_ADPCM &&
1641                 (sfinfo.format & SF_FORMAT_SUBMASK) != SF_FORMAT_GSM610 &&
1642                 (sfinfo.format & SF_FORMAT_SUBMASK) != SF_FORMAT_G721_32 &&
1643                 (sfinfo.format & SF_FORMAT_SUBMASK) != SF_FORMAT_G723_24)
1644                 for (k = 0 ; k < sfinfo.frames - datalen ; k++)
1645                         if (abs (data [k]) > decay_response (k))
1646                         {       printf ("\n\nLine %d: Incorrect sample (#%ld : abs (%d) should be < %d).\n", __LINE__, datalen + k, data [k], decay_response (k)) ;
1647                                 exit (1) ;
1648                                 } ;
1649
1650         /* Now test sf_seek function. */
1651         if (sfinfo.seekable)
1652         {       if ((k = sf_seek (file, 0, SEEK_SET)) != 0)
1653                 {       printf ("\n\nLine %d: Seek to start of file failed (%d).\n", __LINE__, k) ;
1654                         exit (1) ;
1655                         } ;
1656
1657                 for (m = 0 ; m < 3 ; m++)
1658                 {       test_readf_int_or_die (file, m, data, datalen / 7, __LINE__) ;
1659
1660                         smoothed_diff_int (data, datalen / 7) ;
1661                         memcpy (smooth, orig + m * datalen / 7, datalen / 7 * sizeof (int)) ;
1662                         smoothed_diff_int (smooth, datalen / 7) ;
1663
1664                         for (k = 0 ; k < datalen / 7 ; k++)
1665                                 if (error_function (data [k] / scale, smooth [k] / scale, margin))
1666                                 {       printf ("\nLine %d: Incorrect sample (#%d (%ld) : %d => %d).\n", __LINE__, k, k + m * (datalen / 7), smooth [k], data [k]) ;
1667                                         for (m = 0 ; m < 10 ; m++)
1668                                                 printf ("%d ", data [k]) ;
1669                                         printf ("\n") ;
1670                                         exit (1) ;
1671                                         } ;
1672                         } ; /* for (m = 0 ; m < 3 ; m++) */
1673
1674                 seekpos = BUFFER_SIZE / 10 ;
1675
1676                 /* Check seek from start of file. */
1677                 if ((k = sf_seek (file, seekpos, SEEK_SET)) != seekpos)
1678                 {       printf ("Seek to start of file + %d failed (%d).\n", seekpos, k) ;
1679                         exit (1) ;
1680                         } ;
1681                 test_readf_int_or_die (file, 0, data, 1, __LINE__) ;
1682
1683                 if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin))
1684                 {       printf ("\nLine %d: sf_seek (SEEK_SET) followed by sf_readf_int failed (%d, %d).\n", __LINE__, orig [1], data [0]) ;
1685                         exit (1) ;
1686                         } ;
1687
1688                 if ((k = sf_seek (file, 0, SEEK_CUR)) != seekpos + 1)
1689                 {       printf ("\n\nLine %d: sf_seek (SEEK_CUR) with 0 offset failed (%d should be %d)\n", __LINE__, k, seekpos + 1) ;
1690                         exit (1) ;
1691                         } ;
1692
1693                 seekpos = sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ;
1694                 k = sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ;
1695                 test_readf_int_or_die (file, 0, data, 1, __LINE__) ;
1696                 if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin) || k != seekpos)
1697                 {       printf ("\nLine %d: sf_seek (forwards, SEEK_CUR) followed by sf_readf_int failed (%d, %d) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos + 1) ;
1698                         exit (1) ;
1699                         } ;
1700
1701                 seekpos = sf_seek (file, 0, SEEK_CUR) - 20 ;
1702                 /* Check seek backward from current position. */
1703                 k = sf_seek (file, -20, SEEK_CUR) ;
1704                 test_readf_int_or_die (file, 0, data, 1, __LINE__) ;
1705                 if (error_function (1.0 * data [0], 1.0 * orig [seekpos * channels], margin) || k != seekpos)
1706                 {       printf ("\nLine %d: sf_seek (backwards, SEEK_CUR) followed by sf_readf_int failed (%d, %d) (%d, %d).\n", __LINE__, data [0], orig [seekpos * channels], k, seekpos) ;
1707                         exit (1) ;
1708                         } ;
1709
1710                 /* Check that read past end of file returns number of items. */
1711                 sf_seek (file, sfinfo.frames, SEEK_SET) ;
1712
1713                 if ((k = sf_readf_int (file, data, datalen)) != 0)
1714                 {       printf ("\n\nLine %d: Return value from sf_readf_int past end of file incorrect (%d).\n", __LINE__, k) ;
1715                         exit (1) ;
1716                         } ;
1717
1718                 /* Check seek backward from end. */
1719
1720                 if ((k = sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5)
1721                 {       printf ("\n\nLine %d: sf_seek (SEEK_END) returned %d instead of %d.\n", __LINE__, k, 5) ;
1722                         exit (1) ;
1723                         } ;
1724
1725                 test_readf_int_or_die (file, 0, data, 1, __LINE__) ;
1726                 if (error_function (data [0] / scale, orig [5] / scale, margin))
1727                 {       printf ("\nLine %d: sf_seek (SEEK_END) followed by sf_readf_int failed (%d should be %d).\n", __LINE__, data [0], orig [5]) ;
1728                         exit (1) ;
1729                         } ;
1730                 } /* if (sfinfo.seekable) */
1731
1732         sf_close (file) ;
1733
1734         unlink (filename) ;
1735         printf ("ok\n") ;
1736 } /* sdlcomp_test_int */
1737
1738 static void
1739 sdlcomp_test_float      (const char *filename, int filetype, int channels, double margin)
1740 {       SNDFILE                 *file ;
1741         SF_INFO                 sfinfo ;
1742         int                             k, m, seekpos ;
1743         long                    datalen ;
1744         float                   *orig, *data, *smooth ;
1745         double                  half_max_abs ;
1746
1747 channels = 1 ;
1748
1749         print_test_name ("sdlcomp_test_float", filename) ;
1750
1751         if ((filetype & SF_FORMAT_SUBMASK) == SF_FORMAT_VORBIS)
1752         {       puts ("Not working for this format.") ;
1753                 return ;
1754                 } ;
1755
1756 printf ("** fix this ** ") ;
1757
1758         datalen = BUFFER_SIZE ;
1759
1760         orig = orig_buffer.f ;
1761         data = data_buffer.f ;
1762         smooth = smooth_buffer.f ;
1763
1764         gen_signal_double (orig_buffer.d, 32000.0, channels, datalen) ;
1765         for (k = 0 ; k < datalen ; k++)
1766                 orig [k] = lrint (orig_buffer.d [k]) ;
1767
1768         sfinfo.samplerate       = SAMPLE_RATE ;
1769         sfinfo.frames           = 123456789 ;   /* Ridiculous value. */
1770         sfinfo.channels         = channels ;
1771         sfinfo.format           = filetype ;
1772
1773         file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
1774         sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
1775         test_write_float_or_die (file, 0, orig, datalen, __LINE__) ;
1776         sf_set_string (file, SF_STR_COMMENT, long_comment) ;
1777         sf_close (file) ;
1778
1779         memset (data, 0, datalen * sizeof (float)) ;
1780
1781         if ((filetype & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
1782                 memset (&sfinfo, 0, sizeof (sfinfo)) ;
1783
1784         file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
1785
1786         if ((sfinfo.format & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)) != (filetype & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK)))
1787         {       printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
1788                 exit (1) ;
1789                 } ;
1790
1791         if (sfinfo.frames < datalen / channels)
1792         {       printf ("Too few.frames in file. (%ld should be a little more than %ld)\n", datalen, SF_COUNT_TO_LONG (sfinfo.frames)) ;
1793                 exit (1) ;
1794                 } ;
1795
1796         if (sfinfo.frames > (datalen + 400))
1797         {       printf ("Too many.frames in file. (%ld should be a little more than %ld)\n", SF_COUNT_TO_LONG (sfinfo.frames), datalen) ;
1798                 exit (1) ;
1799                 } ;
1800
1801         if (sfinfo.channels != channels)
1802         {       printf ("Incorrect number of channels in file.\n") ;
1803                 exit (1) ;
1804                 } ;
1805
1806         check_comment (file, filetype, __LINE__) ;
1807
1808         sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
1809
1810         check_log_buffer_or_die (file, __LINE__) ;
1811
1812         test_read_float_or_die (file, 0, data, datalen, __LINE__) ;
1813
1814         memcpy (smooth, orig, datalen * sizeof (float)) ;
1815         smoothed_diff_float (data, datalen) ;
1816         smoothed_diff_float (smooth, datalen) ;
1817
1818         half_max_abs = fabs (data [0]) ;
1819         for (k = 1 ; k < datalen ; k++)
1820         {       if (error_function (data [k], smooth [k], margin))
1821                 {       printf ("\nLine %d: Incorrect sample (#%d : %d should be %d).\n", __LINE__, k, (int) data [k], (int) smooth [k]) ;
1822                         oct_save_float (orig, smooth, datalen) ;
1823                         exit (1) ;
1824                         } ;
1825                 half_max_abs = LCT_MAX (half_max_abs, abs (0.5 * data [k])) ;
1826                 } ;
1827
1828         if (half_max_abs <= 0.0)
1829         {       printf ("\n\nLine %d: Signal is all zeros.\n", __LINE__) ;
1830                 printf ("half_max_abs : % 10.6f\n", half_max_abs) ;
1831                 exit (1) ;
1832                 } ;
1833
1834         if ((k = sf_read_float (file, data, datalen)) != sfinfo.frames - datalen)
1835         {       printf ("\n\nLine %d: Incorrect read length (%d should be %ld).\n", __LINE__, k, SF_COUNT_TO_LONG (sfinfo.frames - datalen)) ;
1836                 exit (1) ;
1837                 } ;
1838
1839         if ((sfinfo.format & SF_FORMAT_SUBMASK) != SF_FORMAT_MS_ADPCM &&
1840                 (sfinfo.format & SF_FORMAT_SUBMASK) != SF_FORMAT_GSM610)
1841                 for (k = 0 ; k < sfinfo.frames - datalen ; k++)
1842                         if (abs (data [k]) > decay_response (k))
1843                         {       printf ("\n\nLine %d: Incorrect sample (#%ld : abs (%d) should be < %d).\n", __LINE__, datalen + k, (int) data [k], (int) decay_response (k)) ;
1844                                 exit (1) ;
1845                                 } ;
1846
1847         /* Now test sf_seek function. */
1848         if (sfinfo.seekable)
1849         {       if ((k = sf_seek (file, 0, SEEK_SET)) != 0)
1850                 {       printf ("\n\nLine %d: Seek to start of file failed (%d).\n", __LINE__, k) ;
1851                         exit (1) ;
1852                         } ;
1853
1854                 for (m = 0 ; m < 3 ; m++)
1855                 {       test_read_float_or_die (file, 0, data, datalen / 7, __LINE__) ;
1856
1857                         smoothed_diff_float (data, datalen / 7) ;
1858                         memcpy (smooth, orig + m * datalen / 7, datalen / 7 * sizeof (float)) ;
1859                         smoothed_diff_float (smooth, datalen / 7) ;
1860
1861                         for (k = 0 ; k < datalen / 7 ; k++)
1862                                 if (error_function (data [k], smooth [k], margin))
1863                                 {       printf ("\nLine %d: Incorrect sample C (#%d (%ld) : %d => %d).\n", __LINE__, k, k + m * (datalen / 7), (int) smooth [k], (int) data [k]) ;
1864                                         for (m = 0 ; m < 10 ; m++)
1865                                                 printf ("%d ", (int) data [k]) ;
1866                                         printf ("\n") ;
1867                                         exit (1) ;
1868                                         } ;
1869                         } ; /* for (m = 0 ; m < 3 ; m++) */
1870
1871                 seekpos = BUFFER_SIZE / 10 ;
1872
1873                 /* Check seek from start of file. */
1874                 if ((k = sf_seek (file, seekpos, SEEK_SET)) != seekpos)
1875                 {       printf ("Seek to start of file + %d failed (%d).\n", seekpos, k) ;
1876                         exit (1) ;
1877                         } ;
1878                 test_read_float_or_die (file, 0, data, channels, __LINE__) ;
1879
1880                 if (error_function (data [0], orig [seekpos * channels], margin))
1881                 {       printf ("\nLine %d: sf_seek (SEEK_SET) followed by sf_read_float failed (%d, %d).\n", __LINE__, (int) orig [1], (int) data [0]) ;
1882                         exit (1) ;
1883                         } ;
1884
1885                 if ((k = sf_seek (file, 0, SEEK_CUR)) != seekpos + 1)
1886                 {       printf ("\n\nLine %d: sf_seek (SEEK_CUR) with 0 offset failed (%d should be %d)\n", __LINE__, k, seekpos + 1) ;
1887                         exit (1) ;
1888                         } ;
1889
1890                 seekpos = sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ;
1891                 k = sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ;
1892                 test_read_float_or_die (file, 0, data, channels, __LINE__) ;
1893                 if (error_function (data [0], orig [seekpos * channels], margin) || k != seekpos)
1894                 {       printf ("\nLine %d: sf_seek (forwards, SEEK_CUR) followed by sf_read_float failed (%d, %d) (%d, %d).\n", __LINE__, (int) data [0], (int) orig [seekpos * channels], k, seekpos + 1) ;
1895                         exit (1) ;
1896                         } ;
1897
1898                 seekpos = sf_seek (file, 0, SEEK_CUR) - 20 ;
1899                 /* Check seek backward from current position. */
1900                 k = sf_seek (file, -20, SEEK_CUR) ;
1901                 test_read_float_or_die (file, 0, data, channels, __LINE__) ;
1902                 if (error_function (data [0], orig [seekpos * channels], margin) || k != seekpos)
1903                 {       printf ("\nLine %d: sf_seek (backwards, SEEK_CUR) followed by sf_read_float failed (%d, %d) (%d, %d).\n", __LINE__, (int) data [0], (int) orig [seekpos * channels], k, seekpos) ;
1904                         exit (1) ;
1905                         } ;
1906
1907                 /* Check that read past end of file returns number of items. */
1908                 sf_seek (file, sfinfo.frames, SEEK_SET) ;
1909
1910                 if ((k = sf_read_float (file, data, datalen)) != 0)
1911                 {       printf ("\n\nLine %d: Return value from sf_read_float past end of file incorrect (%d).\n", __LINE__, k) ;
1912                         exit (1) ;
1913                         } ;
1914
1915                 /* Check seek backward from end. */
1916
1917                 if ((k = sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5)
1918                 {       printf ("\n\nLine %d: sf_seek (SEEK_END) returned %d instead of %d.\n", __LINE__, k, 5) ;
1919                         exit (1) ;
1920                         } ;
1921
1922                 test_read_float_or_die (file, 0, data, channels, __LINE__) ;
1923                 if (error_function (data [0], orig [5 * channels], margin))
1924                 {       printf ("\nLine %d: sf_seek (SEEK_END) followed by sf_read_float failed (%f should be %f).\n", __LINE__, data [0], orig [5 * channels]) ;
1925                         exit (1) ;
1926                         } ;
1927                 } /* if (sfinfo.seekable) */
1928
1929         sf_close (file) ;
1930
1931         unlink (filename) ;
1932         printf ("ok\n") ;
1933 } /* sdlcomp_test_float */
1934
1935 static void
1936 sdlcomp_test_double     (const char *filename, int filetype, int channels, double margin)
1937 {       SNDFILE                 *file ;
1938         SF_INFO                 sfinfo ;
1939         int                             k, m, seekpos ;
1940         long                    datalen ;
1941         double                  *orig, *data, *smooth, half_max_abs ;
1942
1943 channels = 1 ;
1944         print_test_name ("sdlcomp_test_double", filename) ;
1945
1946         if ((filetype & SF_FORMAT_SUBMASK) == SF_FORMAT_VORBIS)
1947         {       puts ("Not working for this format.") ;
1948                 return ;
1949                 } ;
1950
1951         datalen = BUFFER_SIZE ;
1952
1953         orig = orig_buffer.d ;
1954         data = data_buffer.d ;
1955         smooth = smooth_buffer.d ;
1956
1957         gen_signal_double (orig_buffer.d, 32000.0, channels, datalen) ;
1958
1959         sfinfo.samplerate       = SAMPLE_RATE ;
1960         sfinfo.frames           = 123456789 ;   /* Ridiculous value. */
1961         sfinfo.channels         = channels ;
1962         sfinfo.format           = filetype ;
1963
1964         file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
1965         sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
1966         test_write_double_or_die (file, 0, orig, datalen, __LINE__) ;
1967         sf_set_string (file, SF_STR_COMMENT, long_comment) ;
1968         sf_close (file) ;
1969
1970         memset (data, 0, datalen * sizeof (double)) ;
1971
1972         if ((filetype & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
1973                 memset (&sfinfo, 0, sizeof (sfinfo)) ;
1974
1975         file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
1976
1977         if (sfinfo.format != filetype)
1978         {       printf ("Returned format incorrect (0x%08X => 0x%08X).\n", filetype, sfinfo.format) ;
1979                 exit (1) ;
1980                 } ;
1981
1982         if (sfinfo.frames < datalen / channels)
1983         {       printf ("Too few.frames in file. (%ld should be a little more than %ld)\n", datalen, SF_COUNT_TO_LONG (sfinfo.frames)) ;
1984                 exit (1) ;
1985                 } ;
1986
1987         if (sfinfo.frames > (datalen + 400))
1988         {       printf ("Too many.frames in file. (%ld should be a little more than %ld)\n", SF_COUNT_TO_LONG (sfinfo.frames), datalen) ;
1989                 exit (1) ;
1990                 } ;
1991
1992         if (sfinfo.channels != channels)
1993         {       printf ("Incorrect number of channels in file.\n") ;
1994                 exit (1) ;
1995                 } ;
1996
1997         check_comment (file, filetype, __LINE__) ;
1998
1999         check_comment (file, filetype, __LINE__) ;
2000
2001         sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
2002
2003         check_log_buffer_or_die (file, __LINE__) ;
2004
2005         test_read_double_or_die (file, 0, data, datalen, __LINE__) ;
2006
2007         memcpy (smooth, orig, datalen * sizeof (double)) ;
2008         smoothed_diff_double (data, datalen) ;
2009         smoothed_diff_double (smooth, datalen) ;
2010
2011         half_max_abs = 0.0 ;
2012         for (k = 0 ; k < datalen ; k++)
2013         {       if (error_function (data [k], smooth [k], margin))
2014                 {       printf ("\n\nLine %d: Incorrect sample (#%d : %d should be %d).\n", __LINE__, k, (int) data [k], (int) smooth [k]) ;
2015                         oct_save_double (orig, smooth, datalen) ;
2016                         exit (1) ;
2017                         } ;
2018                 half_max_abs = LCT_MAX (half_max_abs, 0.5 * fabs (data [k])) ;
2019                 } ;
2020
2021         if (half_max_abs < 1.0)
2022         {       printf ("\n\nLine %d: Signal is all zeros.\n", __LINE__) ;
2023                 exit (1) ;
2024                 } ;
2025
2026         if ((k = sf_read_double (file, data, datalen)) != sfinfo.frames - datalen)
2027         {       printf ("\n\nLine %d: Incorrect read length (%d should be %ld).\n", __LINE__, k, SF_COUNT_TO_LONG (sfinfo.frames - datalen)) ;
2028                 exit (1) ;
2029                 } ;
2030
2031         if ((sfinfo.format & SF_FORMAT_SUBMASK) != SF_FORMAT_MS_ADPCM &&
2032                 (sfinfo.format & SF_FORMAT_SUBMASK) != SF_FORMAT_GSM610)
2033                 for (k = 0 ; k < sfinfo.frames - datalen ; k++)
2034                         if (abs (data [k]) > decay_response (k))
2035                         {       printf ("\n\nLine %d: Incorrect sample (#%ld : abs (%d) should be < %d).\n", __LINE__, datalen + k, (int) data [k], (int) decay_response (k)) ;
2036                                 exit (1) ;
2037                                 } ;
2038
2039         /* Now test sf_seek function. */
2040         if (sfinfo.seekable)
2041         {       if ((k = sf_seek (file, 0, SEEK_SET)) != 0)
2042                 {       printf ("\n\nLine %d: Seek to start of file failed (%d).\n", __LINE__, k) ;
2043                         exit (1) ;
2044                         } ;
2045
2046                 for (m = 0 ; m < 3 ; m++)
2047                 {       test_read_double_or_die (file, m, data, datalen / 7, __LINE__) ;
2048
2049                         smoothed_diff_double (data, datalen / 7) ;
2050                         memcpy (smooth, orig + m * datalen / 7, datalen / 7 * sizeof (double)) ;
2051                         smoothed_diff_double (smooth, datalen / 7) ;
2052
2053                         for (k = 0 ; k < datalen / 7 ; k++)
2054                                 if (error_function (data [k], smooth [k], margin))
2055                                 {       printf ("\nLine %d: Incorrect sample C (#%d (%ld) : %d => %d).\n", __LINE__, k, k + m * (datalen / 7), (int) smooth [k], (int) data [k]) ;
2056                                         for (m = 0 ; m < 10 ; m++)
2057                                                 printf ("%d ", (int) data [k]) ;
2058                                         printf ("\n") ;
2059                                         exit (1) ;
2060                                         } ;
2061                         } ; /* for (m = 0 ; m < 3 ; m++) */
2062
2063                 seekpos = BUFFER_SIZE / 10 ;
2064
2065                 /* Check seek from start of file. */
2066                 if ((k = sf_seek (file, seekpos, SEEK_SET)) != seekpos)
2067                 {       printf ("Seek to start of file + %d failed (%d).\n", seekpos, k) ;
2068                         exit (1) ;
2069                         } ;
2070                 test_read_double_or_die (file, 0, data, channels, __LINE__) ;
2071
2072                 if (error_function (data [0], orig [seekpos * channels], margin))
2073                 {       printf ("\nLine %d: sf_seek (SEEK_SET) followed by sf_read_double failed (%d, %d).\n", __LINE__, (int) orig [1], (int) data [0]) ;
2074                         exit (1) ;
2075                         } ;
2076
2077                 if ((k = sf_seek (file, 0, SEEK_CUR)) != seekpos + 1)
2078                 {       printf ("\n\nLine %d: sf_seek (SEEK_CUR) with 0 offset failed (%d should be %d)\n", __LINE__, k, seekpos + 1) ;
2079                         exit (1) ;
2080                         } ;
2081
2082                 seekpos = sf_seek (file, 0, SEEK_CUR) + BUFFER_SIZE / 5 ;
2083                 k = sf_seek (file, BUFFER_SIZE / 5, SEEK_CUR) ;
2084                 test_read_double_or_die (file, 0, data, channels, __LINE__) ;
2085                 if (error_function (data [0], orig [seekpos * channels], margin) || k != seekpos)
2086                 {       printf ("\nLine %d: sf_seek (forwards, SEEK_CUR) followed by sf_read_double failed (%d, %d) (%d, %d).\n", __LINE__, (int) data [0], (int) orig [seekpos * channels], k, seekpos + 1) ;
2087                         exit (1) ;
2088                         } ;
2089
2090                 seekpos = sf_seek (file, 0, SEEK_CUR) - 20 ;
2091                 /* Check seek backward from current position. */
2092                 k = sf_seek (file, -20, SEEK_CUR) ;
2093                 test_read_double_or_die (file, 0, data, channels, __LINE__) ;
2094                 if (error_function (data [0], orig [seekpos * channels], margin) || k != seekpos)
2095                 {       printf ("\nLine %d: sf_seek (backwards, SEEK_CUR) followed by sf_read_double failed (%d, %d) (%d, %d).\n", __LINE__, (int) data [0], (int) orig [seekpos * channels], k, seekpos) ;
2096                         exit (1) ;
2097                         } ;
2098
2099                 /* Check that read past end of file returns number of items. */
2100                 sf_seek (file, sfinfo.frames, SEEK_SET) ;
2101
2102                 if ((k = sf_read_double (file, data, datalen)) != 0)
2103                 {       printf ("\n\nLine %d: Return value from sf_read_double past end of file incorrect (%d).\n", __LINE__, k) ;
2104                         exit (1) ;
2105                         } ;
2106
2107                 /* Check seek backward from end. */
2108
2109                 if ((k = sf_seek (file, 5 - sfinfo.frames, SEEK_END)) != 5)
2110                 {       printf ("\n\nLine %d: sf_seek (SEEK_END) returned %d instead of %d.\n", __LINE__, k, 5) ;
2111                         exit (1) ;
2112                         } ;
2113
2114                 test_read_double_or_die (file, 0, data, channels, __LINE__) ;
2115                 if (error_function (data [0], orig [5 * channels], margin))
2116                 {       printf ("\nLine %d: sf_seek (SEEK_END) followed by sf_read_double failed (%f should be %f).\n", __LINE__, data [0], orig [5 * channels]) ;
2117                         exit (1) ;
2118                         } ;
2119                 } /* if (sfinfo.seekable) */
2120
2121         sf_close (file) ;
2122
2123         unlink (filename) ;
2124         printf ("ok\n") ;
2125 } /* sdlcomp_test_double */
2126
2127 static void
2128 read_raw_test (const char *filename, int filetype, int channels)
2129 {       SNDFILE                 *file ;
2130         SF_INFO                 sfinfo ;
2131         sf_count_t              count ;
2132         long                    datalen ;
2133         short                   *orig, *data ;
2134         int                             k ;
2135
2136         print_test_name ("read_raw_test", filename) ;
2137
2138         datalen = ARRAY_LEN (orig_buffer.s) / 2 ;
2139
2140         orig = orig_buffer.s ;
2141         data = data_buffer.s ;
2142
2143         gen_signal_double (orig_buffer.d, 32000.0, channels, datalen) ;
2144         for (k = 0 ; k < datalen ; k++)
2145                 orig [k] = lrint (orig_buffer.d [k]) ;
2146
2147         sfinfo.samplerate       = SAMPLE_RATE ;
2148         sfinfo.frames           = 123456789 ;   /* Ridiculous value. */
2149         sfinfo.channels         = channels ;
2150         sfinfo.format           = filetype ;
2151
2152         file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
2153         test_write_short_or_die (file, 0, orig, datalen, __LINE__) ;
2154         sf_set_string (file, SF_STR_COMMENT, long_comment) ;
2155         sf_close (file) ;
2156
2157         memset (data, 0, datalen * sizeof (double)) ;
2158
2159         if ((filetype & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
2160                 memset (&sfinfo, 0, sizeof (sfinfo)) ;
2161
2162         file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
2163
2164         if (sfinfo.format != filetype)
2165         {       printf ("Returned format incorrect (0x%08X => 0x%08X).\n", filetype, sfinfo.format) ;
2166                 exit (1) ;
2167                 } ;
2168
2169         if (sfinfo.frames < datalen / channels)
2170         {       printf ("Too few.frames in file. (%ld should be a little more than %ld)\n", datalen, SF_COUNT_TO_LONG (sfinfo.frames)) ;
2171                 exit (1) ;
2172                 } ;
2173
2174         if (sfinfo.frames > (datalen + 400))
2175         {       printf ("Too many.frames in file. (%ld should be a little more than %ld)\n", SF_COUNT_TO_LONG (sfinfo.frames), datalen) ;
2176                 exit (1) ;
2177                 } ;
2178
2179         if (sfinfo.channels != channels)
2180         {       printf ("Incorrect number of channels in file.\n") ;
2181                 exit (1) ;
2182                 } ;
2183
2184         check_comment (file, filetype, __LINE__) ;
2185
2186         count = sf_read_raw (file, orig_buffer.c, datalen + 5 * channels) ;
2187         if (count != sfinfo.channels * sfinfo.frames)
2188         {       printf ("\nLine %d : sf_read_raw returned %ld should be %ld\n", __LINE__, SF_COUNT_TO_LONG (count), sfinfo.channels * SF_COUNT_TO_LONG (sfinfo.frames)) ;
2189                 exit (1) ;
2190                 } ;
2191
2192         sf_close (file) ;
2193
2194         unlink (filename) ;
2195         printf ("ok\n") ;
2196 } /* read_raw_test */
2197
2198 /*========================================================================================
2199 **      Auxiliary functions
2200 */
2201
2202 #define         SIGNAL_MAXVAL   30000.0
2203 #define         DECAY_COUNT             1000
2204
2205 static int
2206 decay_response (int k)
2207 {       if (k < 1)
2208                 return (int) (1.2 * SIGNAL_MAXVAL) ;
2209         if (k > DECAY_COUNT)
2210                 return 0 ;
2211         return (int) (1.2 * SIGNAL_MAXVAL * (DECAY_COUNT - k) / (1.0 * DECAY_COUNT)) ;
2212 } /* decay_response */
2213
2214 static void
2215 gen_signal_double (double *data, double scale, int channels, int datalen)
2216 {       int             k, ramplen ;
2217         double  amp = 0.0 ;
2218
2219         ramplen = DECAY_COUNT ;
2220
2221         if (channels == 1)
2222         {       for (k = 0 ; k < datalen ; k++)
2223                 {       if (k <= ramplen)
2224                                 amp = scale * k / ((double) ramplen) ;
2225                         else if (k > datalen - ramplen)
2226                                 amp = scale * (datalen - k) / ((double) ramplen) ;
2227
2228 /*-printf ("%3d : %g\n", k, amp) ;-*/
2229
2230                         data [k] = amp * (0.4 * sin (33.3 * 2.0 * M_PI * ((double) (k+1)) / ((double) SAMPLE_RATE))
2231                                                         + 0.3 * cos (201.1 * 2.0 * M_PI * ((double) (k+1)) / ((double) SAMPLE_RATE))) ;
2232                         } ;
2233                 }
2234         else
2235         {       for (k = 0 ; k < datalen ; k ++)
2236                 {       if (k <= ramplen)
2237                                 amp = scale * k / ((double) ramplen) ;
2238                         else if (k > datalen - ramplen)
2239                                 amp = scale * (datalen - k) / ((double) ramplen) ;
2240
2241                         data [2 * k] = amp * (0.4 * sin (33.3 * 2.0 * M_PI * ((double) (k+1)) / ((double) SAMPLE_RATE))
2242                                                         + 0.3 * cos (201.1 * 2.0 * M_PI * ((double) (k+1)) / ((double) SAMPLE_RATE))) ;
2243                         data [2 * k + 1] = amp * (0.4 * sin (55.5 * 2.0 * M_PI * ((double) (k+1)) / ((double) SAMPLE_RATE))
2244                                                         + 0.3 * cos (201.1 * 2.0 * M_PI * ((double) (k+1)) / ((double) SAMPLE_RATE))) ;
2245                         } ;
2246                 } ;
2247
2248         return ;
2249 } /* gen_signal_double */
2250
2251 static int
2252 error_function (double data, double orig, double margin)
2253 {       double error ;
2254
2255         if (fabs (orig) <= 500.0)
2256                 error = fabs (fabs (data) - fabs (orig)) / 2000.0 ;
2257         else if (fabs (orig) <= 1000.0)
2258                 error = fabs (data - orig) / 3000.0 ;
2259         else
2260                 error = fabs (data - orig) / fabs (orig) ;
2261
2262         if (error > margin)
2263         {       printf ("\n\nerror_function (data = %f, orig = %f, margin = %f) -> %f\n", data, orig, margin, error) ;
2264                 return 1 ;
2265                 } ;
2266         return 0 ;
2267 } /* error_function */
2268
2269 static void
2270 smoothed_diff_short (short *data, unsigned int datalen)
2271 {       unsigned int k ;
2272         double memory = 0.0 ;
2273
2274         /* Calculate the smoothed sample-to-sample difference. */
2275         for (k = 0 ; k < datalen - 1 ; k++)
2276         {       memory = 0.7 * memory + (1 - 0.7) * (double) (data [k+1] - data [k]) ;
2277                 data [k] = (short) memory ;
2278                 } ;
2279         data [datalen-1] = data [datalen-2] ;
2280
2281 } /* smoothed_diff_short */
2282
2283 static void
2284 smoothed_diff_int (int *data, unsigned int datalen)
2285 {       unsigned int k ;
2286         double memory = 0.0 ;
2287
2288         /* Calculate the smoothed sample-to-sample difference. */
2289         for (k = 0 ; k < datalen - 1 ; k++)
2290         {       memory = 0.7 * memory + (1 - 0.7) * (double) (data [k+1] - data [k]) ;
2291                 data [k] = (int) memory ;
2292                 } ;
2293         data [datalen-1] = data [datalen-2] ;
2294
2295 } /* smoothed_diff_int */
2296
2297 static  void
2298 smoothed_diff_float (float *data, unsigned int datalen)
2299 {       unsigned int k ;
2300         float memory = 0.0 ;
2301
2302         /* Calculate the smoothed sample-to-sample difference. */
2303         for (k = 0 ; k < datalen - 1 ; k++)
2304         {       memory = 0.7 * memory + (1 - 0.7) * (data [k+1] - data [k]) ;
2305                 data [k] = memory ;
2306                 } ;
2307         data [datalen-1] = data [datalen-2] ;
2308
2309 } /* smoothed_diff_float */
2310
2311 static  void
2312 smoothed_diff_double (double *data, unsigned int datalen)
2313 {       unsigned int k ;
2314         double memory = 0.0 ;
2315
2316         /* Calculate the smoothed sample-to-sample difference. */
2317         for (k = 0 ; k < datalen - 1 ; k++)
2318         {       memory = 0.7 * memory + (1 - 0.7) * (data [k+1] - data [k]) ;
2319                 data [k] = memory ;
2320                 } ;
2321         data [datalen-1] = data [datalen-2] ;
2322
2323 } /* smoothed_diff_double */
2324
2325 static void
2326 check_comment (SNDFILE * file, int format, int lineno)
2327 {       const char              *comment ;
2328
2329         switch (format & SF_FORMAT_TYPEMASK)
2330         {       case SF_FORMAT_AIFF :
2331                 case SF_FORMAT_WAV :
2332                 case SF_FORMAT_WAVEX :
2333                         break ;
2334                 default :
2335                         return ;
2336                 } ;
2337
2338         comment = sf_get_string (file, SF_STR_COMMENT) ;
2339         if (comment == NULL)
2340         {       printf ("\n\nLine %d : File does not contain a comment string.\n\n", lineno) ;
2341                 exit (1) ;
2342                 } ;
2343
2344         if (strcmp (comment, long_comment) != 0)
2345         {       printf ("\n\nLine %d : File comment does not match comment written.\n\n", lineno) ;
2346                 exit (1) ;
2347                 } ;
2348
2349         return ;
2350 } /* check_comment */
2351
2352 static int
2353 is_lossy (int filetype)
2354 {
2355         switch (SF_FORMAT_SUBMASK & filetype)
2356         {       case SF_FORMAT_PCM_U8 :
2357                 case SF_FORMAT_PCM_S8 :
2358                 case SF_FORMAT_PCM_16 :
2359                 case SF_FORMAT_PCM_24 :
2360                 case SF_FORMAT_PCM_32 :
2361                 case SF_FORMAT_FLOAT :
2362                 case SF_FORMAT_DOUBLE :
2363                         return 0 ;
2364
2365                 default :
2366                         break ;
2367                 } ;
2368
2369         return 1 ;
2370 } /* is_lossy */
2371