• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1[+ AutoGen5 template c +]
2/*
3** Copyright (C) 1999-2013 Erik de Castro Lopo <erikd@mega-nerd.com>
4**
5** This program is free software; you can redistribute it and/or modify
6** it under the terms of the GNU General Public License as published by
7** the Free Software Foundation; either version 2 of the License, or
8** (at your option) any later version.
9**
10** This program is distributed in the hope that it will be useful,
11** but WITHOUT ANY WARRANTY; without even the implied warranty of
12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13** GNU General Public License for more details.
14**
15** You should have received a copy of the GNU General Public License
16** along with this program; if not, write to the Free Software
17** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18*/
19
20#include "sfconfig.h"
21
22#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <math.h>
26#include <inttypes.h>
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 << 12)
39
40static void	lrintf_test (void) ;
41
42[+ FOR data_type
43+]static void	pcm_test_[+ (get "name") +]	(const char *filename, int filetype, uint64_t hash) ;
44[+ ENDFOR data_type
45+]
46static void pcm_test_float	(const char *filename, int filetype, uint64_t hash, int replace_float) ;
47static void pcm_test_double	(const char *filename, int filetype, uint64_t hash, int replace_float) ;
48
49typedef union
50{	double	d [BUFFER_SIZE + 1] ;
51	float	f [BUFFER_SIZE + 1] ;
52	int		i [BUFFER_SIZE + 1] ;
53	short	s [BUFFER_SIZE + 1] ;
54} BUFFER ;
55
56/* Data written to the file. */
57static	BUFFER	data_out ;
58
59/* Data read back from the file. */
60static	BUFFER	data_in ;
61
62int
63main (void)
64{
65	lrintf_test () ;
66
67	pcm_test_bits_8	("pcm-s8.raw", SF_FORMAT_RAW | SF_FORMAT_PCM_S8, 0xa335091249dbfLL) ;
68	pcm_test_bits_8	("pcm-u8.raw", SF_FORMAT_RAW | SF_FORMAT_PCM_U8, 0x48c433d695f3fLL) ;
69
70	pcm_test_bits_16 ("le-pcm16.raw", SF_ENDIAN_LITTLE	| SF_FORMAT_RAW | SF_FORMAT_PCM_16, 0xb956c881ebf08LL) ;
71	pcm_test_bits_16 ("be-pcm16.raw", SF_ENDIAN_BIG		| SF_FORMAT_RAW | SF_FORMAT_PCM_16, 0x2f840c55750f8LL) ;
72
73	pcm_test_bits_24 ("le-pcm24.raw", SF_ENDIAN_LITTLE	| SF_FORMAT_RAW | SF_FORMAT_PCM_24, 0xb6a759ab496f8LL) ;
74	pcm_test_bits_24 ("be-pcm24.raw", SF_ENDIAN_BIG		| SF_FORMAT_RAW | SF_FORMAT_PCM_24, 0xf3eaf9c30b6f8LL) ;
75
76	pcm_test_bits_32 ("le-pcm32.raw", SF_ENDIAN_LITTLE	| SF_FORMAT_RAW | SF_FORMAT_PCM_32, 0xaece1c1c17f08LL) ;
77	pcm_test_bits_32 ("be-pcm32.raw", SF_ENDIAN_BIG		| SF_FORMAT_RAW | SF_FORMAT_PCM_32, 0x9ddf142d0b0f8LL) ;
78
79	/* Lite remove start */
80	pcm_test_float	("le-float.raw", SF_ENDIAN_LITTLE	| SF_FORMAT_RAW | SF_FORMAT_FLOAT, 0xad04f7554267aLL, SF_FALSE) ;
81	pcm_test_float	("be-float.raw", SF_ENDIAN_BIG		| SF_FORMAT_RAW | SF_FORMAT_FLOAT, 0xde3e248fa9186LL, SF_FALSE) ;
82
83	pcm_test_double	("le-double.raw", SF_ENDIAN_LITTLE	| SF_FORMAT_RAW | SF_FORMAT_DOUBLE, 0x2726f958f669cLL, SF_FALSE) ;
84	pcm_test_double	("be-double.raw", SF_ENDIAN_BIG	| SF_FORMAT_RAW | SF_FORMAT_DOUBLE, 0x3583f8ee51164LL, SF_FALSE) ;
85
86	pcm_test_float	("le-float.raw", SF_ENDIAN_LITTLE	| SF_FORMAT_RAW | SF_FORMAT_FLOAT, 0xad04f7554267aLL, SF_TRUE) ;
87	pcm_test_float	("be-float.raw", SF_ENDIAN_BIG		| SF_FORMAT_RAW | SF_FORMAT_FLOAT, 0xde3e248fa9186LL, SF_TRUE) ;
88
89	pcm_test_double	("le-double.raw", SF_ENDIAN_LITTLE	| SF_FORMAT_RAW | SF_FORMAT_DOUBLE, 0x2726f958f669cLL, SF_TRUE) ;
90	pcm_test_double	("be-double.raw", SF_ENDIAN_BIG	| SF_FORMAT_RAW | SF_FORMAT_DOUBLE, 0x3583f8ee51164LL, SF_TRUE) ;
91	/* Lite remove end */
92
93	return 0 ;
94} /* main */
95
96/*============================================================================================
97**	Here are the test functions.
98*/
99
100static void
101lrintf_test (void)
102{	int k, items ;
103	float	*float_data ;
104	int		*int_data ;
105
106	print_test_name ("lrintf_test", "") ;
107
108	items = 1024 ;
109
110	float_data = data_out.f ;
111	int_data = data_in.i ;
112
113	for (k = 0 ; k < items ; k++)
114		float_data [k] = (k * ((k % 2) ? 333333.0 : -333333.0)) ;
115
116	for (k = 0 ; k < items ; k++)
117		int_data [k] = lrintf (float_data [k]) ;
118
119	for (k = 0 ; k < items ; k++)
120		if (fabs (int_data [k] - float_data [k]) > 1.0)
121		{	printf ("\n\nLine %d: float : Incorrect sample (#%d : %f => %d).\n", __LINE__, k, float_data [k], int_data [k]) ;
122			exit (1) ;
123			} ;
124
125	printf ("ok\n") ;
126} /* lrintf_test */
127
128[+ FOR data_type
129+]static void
130pcm_test_[+ (get "name") +] (const char *filename, int filetype, uint64_t hash)
131{	SNDFILE		*file ;
132	SF_INFO		sfinfo ;
133	int			k, items, zero_count ;
134	short		*short_out, *short_in ;
135	int			*int_out, *int_in ;
136	/* Lite remove start */
137	float		*float_out, *float_in ;
138	double		*double_out, *double_in ;
139	/* Lite remove end */
140
141	print_test_name ("pcm_test_[+ (get "name") +]", filename) ;
142
143	items = [+ (get "item_count") +] ;
144
145	short_out = data_out.s ;
146	short_in = data_in.s ;
147
148	zero_count = 0 ;
149	for (k = 0 ; k < items ; k++)
150	{	short_out [k] = [+ (get "short_func") +] ;
151		zero_count = short_out [k] ? zero_count : zero_count + 1 ;
152		} ;
153
154	if (zero_count > items / 4)
155	{	printf ("\n\nLine %d: too many zeros.\n", __LINE__) ;
156		exit (1) ;
157		} ;
158
159	sfinfo.samplerate	= 44100 ;
160	sfinfo.frames		= 123456789 ; /* Wrong length. Library should correct this on sf_close. */
161	sfinfo.channels		= 1 ;
162	sfinfo.format		= filetype ;
163
164	file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
165
166	test_write_short_or_die (file, 0, short_out, items, __LINE__) ;
167
168	sf_close (file) ;
169
170	memset (short_in, 0, items * sizeof (short)) ;
171
172	file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
173
174	if (sfinfo.format != filetype)
175	{	printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
176		exit (1) ;
177		} ;
178
179	if (sfinfo.frames != items)
180	{	printf ("\n\nLine %d: Incorrect number of frames in file. (%d => %" PRId64 ")\n", __LINE__, items, sfinfo.frames) ;
181		exit (1) ;
182		} ;
183
184	if (sfinfo.channels != 1)
185	{	printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
186		exit (1) ;
187		} ;
188
189	check_log_buffer_or_die (file, __LINE__) ;
190
191	test_read_short_or_die (file, 0, short_in, items, __LINE__) ;
192
193	for (k = 0 ; k < items ; k++)
194		if (short_out [k] != short_in [k])
195		{	printf ("\n\nLine %d: Incorrect sample (#%d : 0x%x => 0x%x).\n", __LINE__, k, short_out [k], short_in [k]) ;
196			exit (1) ;
197			} ;
198
199	sf_close (file) ;
200
201	/* Finally, check the file hash. */
202	check_file_hash_or_die (filename, hash, __LINE__) ;
203
204	/*--------------------------------------------------------------------------
205	** Test sf_read/write_int ()
206	*/
207	zero_count = 0 ;
208
209	int_out = data_out.i ;
210	int_in = data_in.i ;
211	for (k = 0 ; k < items ; k++)
212	{	int_out [k] = [+ (get "int_func") +] ;
213		zero_count = int_out [k] ? zero_count : zero_count + 1 ;
214		} ;
215
216	if (zero_count > items / 4)
217	{	printf ("\n\nLine %d: too many zeros.\n", __LINE__) ;
218		exit (1) ;
219		} ;
220
221	sfinfo.samplerate	= 44100 ;
222	sfinfo.frames		= 123456789 ; /* Wrong length. Library should correct this on sf_close. */
223	sfinfo.channels		= 1 ;
224	sfinfo.format		= filetype ;
225
226	file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
227
228	test_write_int_or_die (file, 0, int_out, items, __LINE__) ;
229
230	sf_close (file) ;
231
232	memset (int_in, 0, items * sizeof (int)) ;
233
234	file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
235
236	if (sfinfo.format != filetype)
237	{	printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
238		exit (1) ;
239		} ;
240
241	if (sfinfo.frames != items)
242	{	printf ("\n\nLine %d: Incorrect number of frames in file. (%d => %" PRId64 ")\n", __LINE__, items, sfinfo.frames) ;
243		exit (1) ;
244		} ;
245
246	if (sfinfo.channels != 1)
247	{	printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
248		exit (1) ;
249		} ;
250
251	check_log_buffer_or_die (file, __LINE__) ;
252
253	test_read_int_or_die (file, 0, int_in, items, __LINE__) ;
254
255	for (k = 0 ; k < items ; k++)
256		if (int_out [k] != int_in [k])
257		{	printf ("\n\nLine %d: int : Incorrect sample (#%d : 0x%x => 0x%x).\n", __LINE__, k, int_out [k], int_in [k]) ;
258			exit (1) ;
259			} ;
260
261	sf_close (file) ;
262
263	/* Lite remove start */
264	/*--------------------------------------------------------------------------
265	** Test sf_read/write_float ()
266	*/
267	zero_count = 0 ;
268
269	float_out = data_out.f ;
270	float_in = data_in.f ;
271	for (k = 0 ; k < items ; k++)
272	{	float_out [k] = [+ (get "float_func") +] ;
273		zero_count = (fabs (float_out [k]) > 1e-10) ? zero_count : zero_count + 1 ;
274		} ;
275
276	if (zero_count > items / 4)
277	{	printf ("\n\nLine %d: too many zeros (%d/%d).\n", __LINE__, zero_count, items) ;
278		exit (1) ;
279		} ;
280
281	sfinfo.samplerate	= 44100 ;
282	sfinfo.frames		= 123456789 ; /* Wrong length. Library should correct this on sf_close. */
283	sfinfo.channels		= 1 ;
284	sfinfo.format		= filetype ;
285
286	file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
287
288	sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
289
290	test_write_float_or_die (file, 0, float_out, items, __LINE__) ;
291
292	sf_close (file) ;
293
294	memset (float_in, 0, items * sizeof (float)) ;
295
296	file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
297
298	if (sfinfo.format != filetype)
299	{	printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
300		exit (1) ;
301		} ;
302
303	if (sfinfo.frames != items)
304	{	printf ("\n\nLine %d: Incorrect number of frames in file. (%d => %" PRId64 ")\n", __LINE__, items, sfinfo.frames) ;
305		exit (1) ;
306		} ;
307
308	if (sfinfo.channels != 1)
309	{	printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
310		exit (1) ;
311		} ;
312
313	check_log_buffer_or_die (file, __LINE__) ;
314
315	sf_command (file, SFC_SET_NORM_FLOAT, NULL, SF_FALSE) ;
316
317	test_read_float_or_die (file, 0, float_in, items, __LINE__) ;
318
319	for (k = 0 ; k < items ; k++)
320		if (fabs (float_out [k] - float_in [k]) > 1e-10)
321		{	printf ("\n\nLine %d: float : Incorrect sample (#%d : %f => %f).\n", __LINE__, k, (double) float_out [k], (double) float_in [k]) ;
322			exit (1) ;
323			} ;
324
325	sf_close (file) ;
326
327	/*--------------------------------------------------------------------------
328	** Test sf_read/write_double ()
329	*/
330	zero_count = 0 ;
331
332	double_out = data_out.d ;
333	double_in = data_in.d ;
334	for (k = 0 ; k < items ; k++)
335	{	double_out [k] = [+ (get "float_func") +] ;
336		zero_count = (fabs (double_out [k]) > 1e-10) ? zero_count : zero_count + 1 ;
337		} ;
338
339	if (zero_count > items / 4)
340	{	printf ("\n\nLine %d: too many zeros (%d/%d).\n", __LINE__, zero_count, items) ;
341		exit (1) ;
342		} ;
343
344	sfinfo.samplerate	= 44100 ;
345	sfinfo.frames		= 123456789 ; /* Wrong length. Library should correct this on sf_close. */
346	sfinfo.channels		= 1 ;
347	sfinfo.format		= filetype ;
348
349	file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
350
351	sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
352
353	test_write_double_or_die (file, 0, double_out, items, __LINE__) ;
354
355	sf_close (file) ;
356
357	memset (double_in, 0, items * sizeof (double)) ;
358
359	file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
360
361	if (sfinfo.format != filetype)
362	{	printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
363		exit (1) ;
364		} ;
365
366	if (sfinfo.frames != items)
367	{	printf ("\n\nLine %d: Incorrect number of frames in file. (%d => %" PRId64 ")\n", __LINE__, items, sfinfo.frames) ;
368		exit (1) ;
369		} ;
370
371	if (sfinfo.channels != 1)
372	{	printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
373		exit (1) ;
374		} ;
375
376	check_log_buffer_or_die (file, __LINE__) ;
377
378	sf_command (file, SFC_SET_NORM_DOUBLE, NULL, SF_FALSE) ;
379
380	test_read_double_or_die (file, 0, double_in, items, __LINE__) ;
381
382	for (k = 0 ; k < items ; k++)
383		if (fabs (double_out [k] - double_in [k]) > 1e-10)
384		{	printf ("\n\nLine %d: double : Incorrect sample (#%d : %f => %f).\n", __LINE__, k, double_out [k], double_in [k]) ;
385			exit (1) ;
386			} ;
387
388	sf_close (file) ;
389	/* Lite remove end */
390	unlink (filename) ;
391
392	puts ("ok") ;
393} /* pcm_test_[+ (get "name") +] */
394
395[+ ENDFOR data_type
396+]
397
398/*==============================================================================
399*/
400
401static void
402pcm_test_float (const char *filename, int filetype, uint64_t hash, int replace_float)
403{	SNDFILE			*file ;
404	SF_INFO			sfinfo ;
405	int				k, items, frames ;
406	int				sign ;
407	double			*data, error ;
408
409	print_test_name (replace_float ? "pcm_test_float (replace)" : "pcm_test_float", filename) ;
410
411	items = BUFFER_SIZE ;
412
413	data = data_out.d ;
414	for (sign = 1, k = 0 ; k < items ; k++)
415	{	data [k] = ((double) (k * sign)) / 100.0 ;
416		sign = (sign > 0) ? -1 : 1 ;
417		} ;
418
419	sfinfo.samplerate	= 44100 ;
420	sfinfo.frames		= items ;
421	sfinfo.channels		= 1 ;
422	sfinfo.format		= filetype ;
423
424	file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
425	sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ;
426	if (replace_float && string_in_log_buffer (file, "Using IEEE replacement") == 0)
427	{	printf ("\n\nLine %d : Float replacement code not working.\n\n", __LINE__) ;
428		dump_log_buffer (file) ;
429		exit (1) ;
430		} ;
431
432	test_write_double_or_die (file, 0, data, items, __LINE__) ;
433
434	sf_close (file) ;
435
436	check_file_hash_or_die (filename, hash, __LINE__) ;
437
438	memset (data, 0, items * sizeof (double)) ;
439
440	if ((filetype & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
441		memset (&sfinfo, 0, sizeof (sfinfo)) ;
442
443	file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
444	sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ;
445	if (replace_float && string_in_log_buffer (file, "Using IEEE replacement") == 0)
446	{	printf ("\n\nLine %d : Float replacement code not working.\n\n", __LINE__) ;
447		dump_log_buffer (file) ;
448		exit (1) ;
449		} ;
450
451	if (sfinfo.format != filetype)
452	{	printf ("\n\nError (%s:%d) Mono : Returned format incorrect (0x%08X => 0x%08X).\n", __FILE__, __LINE__, filetype, sfinfo.format) ;
453		exit (1) ;
454		} ;
455
456	if (sfinfo.frames != items)
457	{	printf ("\n\nError (%s:%d) Mono : Incorrect number of frames in file. (%d => %" PRId64 ")\n", __FILE__, __LINE__, items, sfinfo.frames) ;
458		exit (1) ;
459		} ;
460
461	if (sfinfo.channels != 1)
462	{	printf ("\n\nError (%s:%d) Mono : Incorrect number of channels in file.\n", __FILE__, __LINE__) ;
463		exit (1) ;
464		} ;
465
466	check_log_buffer_or_die (file, __LINE__) ;
467
468	test_read_double_or_die (file, 0, data, items, __LINE__) ;
469
470	for (sign = -1, k = 0 ; k < items ; k++)
471	{	error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
472		if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
473		{	printf ("\n\nError (%s:%d) Mono : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
474			exit (1) ;
475			} ;
476		} ;
477
478	/* Seek to end of file. */
479	test_seek_or_die (file, 0, SEEK_END, sfinfo.frames, sfinfo.channels, __LINE__) ;
480
481	/* Seek to start of file. */
482	test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
483
484	test_read_double_or_die (file, 0, data, 4, __LINE__) ;
485	for (k = 0 ; k < 4 ; k++)
486	{	error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
487		if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
488		{	printf ("\n\nError (%s:%d) Mono : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
489			exit (1) ;
490			} ;
491		} ;
492
493	/* Seek to offset from start of file. */
494	test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ;
495
496	test_read_double_or_die (file, 0, data + 10, 4, __LINE__) ;
497	for (k = 10 ; k < 14 ; k++)
498	{	error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
499		if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
500		{	printf ("\n\nError (%s:%d) Mono : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
501			exit (1) ;
502			} ;
503		} ;
504
505	/* Seek to offset from current position. */
506	test_seek_or_die (file, 6, SEEK_CUR, 20, sfinfo.channels, __LINE__) ;
507
508	test_read_double_or_die (file, 0, data + 20, 4, __LINE__) ;
509	for (k = 20 ; k < 24 ; k++)
510	{	error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
511		if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
512		{	printf ("\n\nError (%s:%d) Mono : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
513			exit (1) ;
514			} ;
515		} ;
516
517	/* Seek to offset from end of file. */
518	test_seek_or_die (file, -1 * (sfinfo.frames - 10), SEEK_END, 10, sfinfo.channels, __LINE__) ;
519
520	test_read_double_or_die (file, 0, data + 10, 4, __LINE__) ;
521	for (k = 10 ; k < 14 ; k++)
522	{	error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
523		if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
524		{	printf ("\n\nError (%s:%d) Mono : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
525			exit (1) ;
526			} ;
527		} ;
528
529	sf_close (file) ;
530
531	/* Now test Stereo. */
532
533	if ((filetype & SF_FORMAT_TYPEMASK) == SF_FORMAT_SVX) /* SVX is mono only */
534	{	printf ("ok\n") ;
535		return ;
536		} ;
537
538	items = BUFFER_SIZE ;
539
540	data = data_out.d ;
541	for (sign = -1, k = 0 ; k < items ; k++)
542		data [k] = ((double) k) / 100.0 * (sign *= -1) ;
543
544	sfinfo.samplerate	= 44100 ;
545	sfinfo.frames		= items ;
546	sfinfo.channels		= 2 ;
547	sfinfo.format		= filetype ;
548
549	frames = items / sfinfo.channels ;
550
551	file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
552	sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ;
553	if (replace_float && string_in_log_buffer (file, "Using IEEE replacement") == 0)
554	{	printf ("\n\nLine %d : Float replacement code not working.\n\n", __LINE__) ;
555		dump_log_buffer (file) ;
556		exit (1) ;
557		} ;
558
559	test_writef_double_or_die (file, 0, data, frames, __LINE__) ;
560
561	sf_close (file) ;
562
563	check_file_hash_or_die (filename, hash, __LINE__) ;
564
565	memset (data, 0, items * sizeof (double)) ;
566
567	if ((filetype & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
568		memset (&sfinfo, 0, sizeof (sfinfo)) ;
569
570	file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
571	sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ;
572	if (replace_float && string_in_log_buffer (file, "Using IEEE replacement") == 0)
573	{	printf ("\n\nLine %d : Float replacement code not working.\n\n", __LINE__) ;
574		dump_log_buffer (file) ;
575		exit (1) ;
576		} ;
577
578	if (sfinfo.format != filetype)
579	{	printf ("\n\nError (%s:%d) Stereo : Returned format incorrect (0x%08X => 0x%08X).\n", __FILE__, __LINE__, filetype, sfinfo.format) ;
580		exit (1) ;
581		} ;
582
583	if (sfinfo.frames != frames)
584	{	printf ("\n\nError (%s:%d) Stereo : Incorrect number of frames in file. (%d => %" PRId64 ")\n", __FILE__, __LINE__, frames, sfinfo.frames) ;
585		exit (1) ;
586		} ;
587
588	if (sfinfo.channels != 2)
589	{	printf ("\n\nError (%s:%d) Stereo : Incorrect number of channels in file.\n", __FILE__, __LINE__) ;
590		exit (1) ;
591		} ;
592
593	check_log_buffer_or_die (file, __LINE__) ;
594
595	test_readf_double_or_die (file, 0, data, frames, __LINE__) ;
596	for (sign = -1, k = 0 ; k < items ; k++)
597	{	error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
598		if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
599		{	printf ("\n\nError (%s:%d) Stereo : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
600			exit (1) ;
601			} ;
602		} ;
603
604	/* Seek to start of file. */
605	test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
606
607	test_readf_double_or_die (file, 0, data, 4, __LINE__) ;
608	for (k = 0 ; k < 4 ; k++)
609	{	error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
610		if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
611		{	printf ("\n\nError (%s:%d) Stereo : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
612			exit (1) ;
613			} ;
614		} ;
615
616	/* Seek to offset from start of file. */
617	test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ;
618
619	test_readf_double_or_die (file, 0, data + 20, 2, __LINE__) ;
620	for (k = 20 ; k < 24 ; k++)
621	{	error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
622		if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
623		{	printf ("\n\nError (%s:%d) Stereo : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
624			exit (1) ;
625			} ;
626		} ;
627
628	/* Seek to offset from current position. */
629	test_seek_or_die (file, 8, SEEK_CUR, 20, sfinfo.channels, __LINE__) ;
630
631	test_readf_double_or_die (file, 0, data + 40, 2, __LINE__) ;
632	for (k = 40 ; k < 44 ; k++)
633	{	error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
634		if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
635		{	printf ("\n\nError (%s:%d) Stereo : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
636			exit (1) ;
637			} ;
638		} ;
639
640	/* Seek to offset from end of file. */
641	test_seek_or_die (file, -1 * (sfinfo.frames - 10), SEEK_END, 10, sfinfo.channels, __LINE__) ;
642
643	test_readf_double_or_die (file, 0, data + 20, 2, __LINE__) ;
644	for (k = 20 ; k < 24 ; k++)
645	{	error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
646		if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
647		{	printf ("\n\nError (%s:%d) Stereo : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
648			exit (1) ;
649			} ;
650		} ;
651
652	sf_close (file) ;
653
654	printf ("ok\n") ;
655	unlink (filename) ;
656} /* pcm_test_float */
657
658static void
659pcm_test_double (const char *filename, int	filetype, uint64_t hash, int replace_float)
660{	SNDFILE			*file ;
661	SF_INFO			sfinfo ;
662	int				k, items, frames ;
663	int				sign ;
664	double			*data, error ;
665
666	/* This is the best test routine. Other should be brought up to this standard. */
667
668	print_test_name (replace_float ? "pcm_test_double (replace)" : "pcm_test_double", filename) ;
669
670	items = BUFFER_SIZE ;
671
672	data = data_out.d ;
673	for (sign = 1, k = 0 ; k < items ; k++)
674	{	data [k] = ((double) (k * sign)) / 100.0 ;
675		sign = (sign > 0) ? -1 : 1 ;
676		} ;
677
678	sfinfo.samplerate	= 44100 ;
679	sfinfo.frames		= items ;
680	sfinfo.channels		= 1 ;
681	sfinfo.format		= filetype ;
682
683	file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
684	sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ;
685	if (replace_float && string_in_log_buffer (file, "Using IEEE replacement") == 0)
686	{	printf ("\n\nLine %d : Float replacement code not working.\n\n", __LINE__) ;
687		dump_log_buffer (file) ;
688		exit (1) ;
689		} ;
690
691	test_write_double_or_die (file, 0, data, items, __LINE__) ;
692
693	sf_close (file) ;
694
695	check_file_hash_or_die (filename, hash, __LINE__) ;
696
697	memset (data, 0, items * sizeof (double)) ;
698
699	if ((filetype & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
700		memset (&sfinfo, 0, sizeof (sfinfo)) ;
701
702	file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
703	sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ;
704	if (replace_float && string_in_log_buffer (file, "Using IEEE replacement") == 0)
705	{	printf ("\n\nLine %d : Float replacement code not working.\n\n", __LINE__) ;
706		dump_log_buffer (file) ;
707		exit (1) ;
708		} ;
709
710	if (sfinfo.format != filetype)
711	{	printf ("\n\nError (%s:%d) Mono : Returned format incorrect (0x%08X => 0x%08X).\n", __FILE__, __LINE__, filetype, sfinfo.format) ;
712		exit (1) ;
713		} ;
714
715	if (sfinfo.frames != items)
716	{	printf ("\n\nError (%s:%d) Mono : Incorrect number of frames in file. (%d => %" PRId64 ")\n", __FILE__, __LINE__, items, sfinfo.frames) ;
717		exit (1) ;
718		} ;
719
720	if (sfinfo.channels != 1)
721	{	printf ("\n\nError (%s:%d) Mono : Incorrect number of channels in file.\n", __FILE__, __LINE__) ;
722		exit (1) ;
723		} ;
724
725	check_log_buffer_or_die (file, __LINE__) ;
726
727	test_read_double_or_die (file, 0, data, items, __LINE__) ;
728
729	for (sign = -1, k = 0 ; k < items ; k++)
730	{	error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
731		if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
732		{	printf ("\n\nError (%s:%d) Mono : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
733			exit (1) ;
734			} ;
735		} ;
736
737	/* Seek to start of file. */
738	test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
739
740	test_read_double_or_die (file, 0, data, 4, __LINE__) ;
741	for (k = 0 ; k < 4 ; k++)
742	{	error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
743		if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
744		{	printf ("\n\nError (%s:%d) Mono : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
745			exit (1) ;
746			} ;
747		} ;
748
749	/* Seek to offset from start of file. */
750	test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ;
751
752	test_read_double_or_die (file, 0, data + 10, 4, __LINE__) ;
753
754	test_seek_or_die (file, 0, SEEK_CUR, 14, sfinfo.channels, __LINE__) ;
755
756	for (k = 10 ; k < 14 ; k++)
757	{	error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
758		if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
759		{	printf ("\n\nError (%s:%d) Mono : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
760			exit (1) ;
761			} ;
762		} ;
763
764	/* Seek to offset from current position. */
765	test_seek_or_die (file, 6, SEEK_CUR, 20, sfinfo.channels, __LINE__) ;
766
767	test_read_double_or_die (file, 0, data + 20, 4, __LINE__) ;
768	for (k = 20 ; k < 24 ; k++)
769	{	error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
770		if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
771		{	printf ("\n\nError (%s:%d) Mono : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
772			exit (1) ;
773			} ;
774		} ;
775
776	/* Seek to offset from end of file. */
777	test_seek_or_die (file, -1 * (sfinfo.frames - 10), SEEK_END, 10, sfinfo.channels, __LINE__) ;
778
779	test_read_double_or_die (file, 0, data + 10, 4, __LINE__) ;
780	for (k = 10 ; k < 14 ; k++)
781	{	error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
782		if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
783		{	printf ("\n\nError (%s:%d) Mono : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
784			exit (1) ;
785			} ;
786		} ;
787
788	sf_close (file) ;
789
790	/* Now test Stereo. */
791
792	if ((filetype & SF_FORMAT_TYPEMASK) == SF_FORMAT_SVX) /* SVX is mono only */
793	{	printf ("ok\n") ;
794		return ;
795		} ;
796
797	items = BUFFER_SIZE ;
798
799	data = data_out.d ;
800	for (sign = -1, k = 0 ; k < items ; k++)
801		data [k] = ((double) k) / 100.0 * (sign *= -1) ;
802
803	sfinfo.samplerate	= 44100 ;
804	sfinfo.frames		= items ;
805	sfinfo.channels		= 2 ;
806	sfinfo.format		= filetype ;
807
808	frames = items / sfinfo.channels ;
809
810	file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
811	sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ;
812	if (replace_float && string_in_log_buffer (file, "Using IEEE replacement") == 0)
813	{	printf ("\n\nLine %d : Float replacement code not working.\n\n", __LINE__) ;
814		dump_log_buffer (file) ;
815		exit (1) ;
816		} ;
817
818	test_writef_double_or_die (file, 0, data, frames, __LINE__) ;
819
820	sf_close (file) ;
821
822	check_file_hash_or_die (filename, hash, __LINE__) ;
823
824	memset (data, 0, items * sizeof (double)) ;
825
826	if ((filetype & SF_FORMAT_TYPEMASK) != SF_FORMAT_RAW)
827		memset (&sfinfo, 0, sizeof (sfinfo)) ;
828
829	file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
830	sf_command (file, SFC_TEST_IEEE_FLOAT_REPLACE, NULL, replace_float) ;
831	if (replace_float && string_in_log_buffer (file, "Using IEEE replacement") == 0)
832	{	printf ("\n\nLine %d : Float replacement code not working.\n\n", __LINE__) ;
833		dump_log_buffer (file) ;
834		exit (1) ;
835		} ;
836
837	if (sfinfo.format != filetype)
838	{	printf ("\n\nError (%s:%d) Stereo : Returned format incorrect (0x%08X => 0x%08X).\n", __FILE__, __LINE__, filetype, sfinfo.format) ;
839		exit (1) ;
840		} ;
841
842	if (sfinfo.frames != frames)
843	{	printf ("\n\nError (%s:%d) Stereo : Incorrect number of frames in file. (%d => %" PRId64 ")\n", __FILE__, __LINE__, frames, sfinfo.frames) ;
844		exit (1) ;
845		} ;
846
847	if (sfinfo.channels != 2)
848	{	printf ("\n\nError (%s:%d) Stereo : Incorrect number of channels in file.\n", __FILE__, __LINE__) ;
849		exit (1) ;
850		} ;
851
852	check_log_buffer_or_die (file, __LINE__) ;
853
854	test_readf_double_or_die (file, 0, data, frames, __LINE__) ;
855
856	for (sign = -1, k = 0 ; k < items ; k++)
857	{	error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
858		if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
859		{	printf ("\n\nError (%s:%d) Stereo : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
860			exit (1) ;
861			} ;
862		} ;
863
864	/* Seek to start of file. */
865	test_seek_or_die (file, 0, SEEK_SET, 0, sfinfo.channels, __LINE__) ;
866
867	test_read_double_or_die (file, 0, data, 4, __LINE__) ;
868	for (k = 0 ; k < 4 ; k++)
869	{	error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
870		if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
871		{	printf ("\n\nError (%s:%d) Stereo : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
872			exit (1) ;
873			} ;
874		} ;
875
876	/* Seek to offset from start of file. */
877	test_seek_or_die (file, 10, SEEK_SET, 10, sfinfo.channels, __LINE__) ;
878
879	test_read_double_or_die (file, 0, data + 10, 4, __LINE__) ;
880	for (k = 20 ; k < 24 ; k++)
881	{	error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
882		if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
883		{	printf ("\n\nError (%s:%d) Stereo : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
884			exit (1) ;
885			} ;
886		} ;
887
888	/* Seek to offset from current position. */
889	test_seek_or_die (file, 8, SEEK_CUR, 20, sfinfo.channels, __LINE__) ;
890
891	test_readf_double_or_die (file, 0, data + 40, 4, __LINE__) ;
892	for (k = 40 ; k < 44 ; k++)
893	{	error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
894		if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
895		{	printf ("\n\nError (%s:%d) Stereo : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
896			exit (1) ;
897			} ;
898		} ;
899
900	/* Seek to offset from end of file. */
901	test_seek_or_die (file, -1 * (sfinfo.frames -10), SEEK_END, 10, sfinfo.channels, __LINE__) ;
902
903	test_readf_double_or_die (file, 0, data + 20, 4, __LINE__) ;
904	for (k = 20 ; k < 24 ; k++)
905	{	error = fabs (data [k] - ((double) k) / 100.0 * (sign *= -1)) ;
906		if (fabs (data [k]) > 1e-100 && fabs (error / data [k]) > 1e-5)
907		{	printf ("\n\nError (%s:%d) Stereo : Incorrect sample (#%d : %f => %f).\n", __FILE__, __LINE__, k, ((double) k) / 100.0, data [k]) ;
908			exit (1) ;
909			} ;
910		} ;
911
912	sf_close (file) ;
913
914	printf ("ok\n") ;
915	unlink (filename) ;
916} /* pcm_test_double */
917
918/*==============================================================================
919*/
920