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
main(int argc,char * argv[])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
lcomp_test_short(const char * filename,int filetype,int channels,double margin)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
lcomp_test_int(const char * filename,int filetype,int channels,double margin)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
lcomp_test_float(const char * filename,int filetype,int channels,double margin)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
lcomp_test_double(const char * filename,int filetype,int channels,double margin)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
sdlcomp_test_short(const char * filename,int filetype,int channels,double margin)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
sdlcomp_test_int(const char * filename,int filetype,int channels,double margin)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
sdlcomp_test_float(const char * filename,int filetype,int channels,double margin)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
sdlcomp_test_double(const char * filename,int filetype,int channels,double margin)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
read_raw_test(const char * filename,int filetype,int channels)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
decay_response(int k)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
gen_signal_double(double * data,double scale,int channels,int datalen)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
error_function(double data,double orig,double margin)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
smoothed_diff_short(short * data,unsigned int datalen)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
smoothed_diff_int(int * data,unsigned int datalen)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
smoothed_diff_float(float * data,unsigned int datalen)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
smoothed_diff_double(double * data,unsigned int datalen)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
check_comment(SNDFILE * file,int format,int lineno)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
is_lossy(int filetype)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
check_opus_version(SNDFILE * file)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 */
2618