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