• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1[+ AutoGen5 template c +]
2/*
3** Copyright (C) 2001-2017 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 <inttypes.h>
26#include <math.h>
27
28#include <sys/stat.h>
29
30#if HAVE_UNISTD_H
31#include <unistd.h>
32#endif
33
34#if (HAVE_DECL_S_IRGRP == 0)
35#include <sf_unistd.h>
36#endif
37
38#if (defined (WIN32) || defined (_WIN32))
39#include <io.h>
40#include <direct.h>
41#endif
42
43#include	<sndfile.h>
44
45#include	"utils.h"
46
47#define	BUFFER_LEN		(1 << 10)
48#define LOG_BUFFER_SIZE	1024
49
50static void	update_header_test (const char *filename, int typemajor) ;
51static void	update_header_before_write_test (const char *filename, int typemajor) ;
52
53[+ FOR data_type
54+]static void	update_seek_[+ (get "name") +]_test	(const char *filename, int filetype) ;
55[+ ENDFOR data_type
56+]
57
58static void extra_header_test (const char *filename, int filetype) ;
59
60static void header_shrink_test (const char *filename, int filetype) ;
61
62/* Force the start of this buffer to be double aligned. Sparc-solaris will
63** choke if its not.
64*/
65static	int	data_out [BUFFER_LEN] ;
66static	int	data_in	[BUFFER_LEN] ;
67
68int
69main (int argc, char *argv [])
70{	int		do_all = 0 ;
71	int		test_count = 0 ;
72
73	if (argc != 2)
74	{	printf ("Usage : %s <test>\n", argv [0]) ;
75		printf ("    Where <test> is one of the following:\n") ;
76		printf ("           wav  - test WAV file peak chunk\n") ;
77		printf ("           aiff - test AIFF file PEAK chunk\n") ;
78		printf ("           all  - perform all tests\n") ;
79		exit (1) ;
80		} ;
81
82	do_all= !strcmp (argv [1], "all") ;
83
84	if (do_all || ! strcmp (argv [1], "wav"))
85	{	update_header_test ("header.wav", SF_FORMAT_WAV) ;
86		update_seek_short_test ("header_short.wav", SF_FORMAT_WAV) ;
87		update_seek_int_test ("header_int.wav", SF_FORMAT_WAV) ;
88		update_seek_float_test ("header_float.wav", SF_FORMAT_WAV) ;
89		update_seek_double_test ("header_double.wav", SF_FORMAT_WAV) ;
90		header_shrink_test ("header_shrink.wav", SF_FORMAT_WAV) ;
91		extra_header_test ("extra.wav", SF_FORMAT_WAV) ;
92
93		update_header_test ("header.wavex", SF_FORMAT_WAVEX) ;
94		update_seek_short_test ("header_short.wavex", SF_FORMAT_WAVEX) ;
95		update_seek_int_test ("header_int.wavex", SF_FORMAT_WAVEX) ;
96		update_seek_float_test ("header_float.wavex", SF_FORMAT_WAVEX) ;
97		update_seek_double_test ("header_double.wavex", SF_FORMAT_WAVEX) ;
98		header_shrink_test ("header_shrink.wavex", SF_FORMAT_WAVEX) ;
99		extra_header_test ("extra.wavex", SF_FORMAT_WAVEX) ;
100		test_count++ ;
101		} ;
102
103	if (do_all || ! strcmp (argv [1], "aiff"))
104	{	update_header_test ("header.aiff", SF_FORMAT_AIFF) ;
105		update_seek_short_test ("header_short.aiff", SF_FORMAT_AIFF) ;
106		update_seek_int_test ("header_int.aiff", SF_FORMAT_AIFF) ;
107		update_seek_float_test ("header_float.aiff", SF_FORMAT_AIFF) ;
108		update_seek_double_test ("header_double.aiff", SF_FORMAT_AIFF) ;
109		header_shrink_test ("header_shrink.aiff", SF_FORMAT_AIFF) ;
110		extra_header_test ("extra.aiff", SF_FORMAT_AIFF) ;
111		test_count++ ;
112		} ;
113
114	if (do_all || ! strcmp (argv [1], "au"))
115	{	update_header_test ("header.au", SF_FORMAT_AU) ;
116		update_seek_short_test ("header_short.au", SF_FORMAT_AU) ;
117		update_seek_int_test ("header_int.au", SF_FORMAT_AU) ;
118		update_seek_float_test ("header_float.au", SF_FORMAT_AU) ;
119		update_seek_double_test ("header_double.au", SF_FORMAT_AU) ;
120		test_count++ ;
121		} ;
122
123	if (do_all || ! strcmp (argv [1], "caf"))
124	{	update_header_test ("header.caf", SF_FORMAT_CAF) ;
125		update_seek_short_test ("header_short.caf", SF_FORMAT_CAF) ;
126		update_seek_int_test ("header_int.caf", SF_FORMAT_CAF) ;
127		update_seek_float_test ("header_float.caf", SF_FORMAT_CAF) ;
128		update_seek_double_test ("header_double.caf", SF_FORMAT_CAF) ;
129		/* extra_header_test ("extra.caf", SF_FORMAT_CAF) ; */
130		test_count++ ;
131		} ;
132
133	if (do_all || ! strcmp (argv [1], "nist"))
134	{	update_header_test ("header.nist", SF_FORMAT_NIST) ;
135		update_seek_short_test ("header_short.nist", SF_FORMAT_NIST) ;
136		update_seek_int_test ("header_int.nist", SF_FORMAT_NIST) ;
137		test_count++ ;
138		} ;
139
140	if (do_all || ! strcmp (argv [1], "paf"))
141	{	update_header_test ("header.paf", SF_FORMAT_PAF) ;
142		update_seek_short_test ("header_short.paf", SF_FORMAT_PAF) ;
143		test_count++ ;
144		} ;
145
146	if (do_all || ! strcmp (argv [1], "ircam"))
147	{	update_header_test ("header.ircam", SF_FORMAT_IRCAM) ;
148		update_seek_short_test ("header_short.ircam", SF_FORMAT_IRCAM) ;
149		test_count++ ;
150		} ;
151
152	if (do_all || ! strcmp (argv [1], "w64"))
153	{	update_header_test ("header.w64", SF_FORMAT_W64) ;
154		update_seek_short_test ("header_short.w64", SF_FORMAT_W64) ;
155		update_seek_int_test ("header_int.w64", SF_FORMAT_W64) ;
156		update_seek_float_test ("header_float.w64", SF_FORMAT_W64) ;
157		update_seek_double_test ("header_double.w64", SF_FORMAT_W64) ;
158		test_count++ ;
159		} ;
160
161	if (do_all || ! strcmp (argv [1], "rf64"))
162	{	update_header_test ("header.rf64", SF_FORMAT_RF64) ;
163		update_seek_short_test ("header_short.rf64", SF_FORMAT_RF64) ;
164		update_seek_int_test ("header_int.rf64", SF_FORMAT_RF64) ;
165		update_seek_float_test ("header_float.rf64", SF_FORMAT_RF64) ;
166		update_seek_double_test ("header_double.rf64", SF_FORMAT_RF64) ;
167		test_count++ ;
168		} ;
169
170	if (do_all || ! strcmp (argv [1], "mat4"))
171	{	update_header_test ("header.mat4", SF_FORMAT_MAT4) ;
172		update_seek_short_test ("header_short.mat4", SF_FORMAT_MAT4) ;
173		update_seek_int_test ("header_int.mat4", SF_FORMAT_MAT4) ;
174		update_seek_float_test ("header_float.mat4", SF_FORMAT_MAT4) ;
175		update_seek_double_test ("header_double.mat4", SF_FORMAT_MAT4) ;
176		test_count++ ;
177		} ;
178
179	if (do_all || ! strcmp (argv [1], "mat5"))
180	{	update_header_test ("header.mat5", SF_FORMAT_MAT5) ;
181		update_seek_short_test ("header_short.mat5", SF_FORMAT_MAT5) ;
182		update_seek_int_test ("header_int.mat5", SF_FORMAT_MAT5) ;
183		update_seek_float_test ("header_float.mat5", SF_FORMAT_MAT5) ;
184		update_seek_double_test ("header_double.mat5", SF_FORMAT_MAT5) ;
185		test_count++ ;
186		} ;
187
188	if (do_all || ! strcmp (argv [1], "pvf"))
189	{	update_header_test ("header.pvf", SF_FORMAT_PVF) ;
190		update_seek_short_test ("header_short.pvf", SF_FORMAT_PVF) ;
191		test_count++ ;
192		} ;
193
194	if (do_all || ! strcmp (argv [1], "avr"))
195	{	update_header_test ("header.avr", SF_FORMAT_AVR) ;
196		update_seek_short_test ("header_short.avr", SF_FORMAT_AVR) ;
197		test_count++ ;
198		} ;
199
200	if (do_all || ! strcmp (argv [1], "htk"))
201	{	update_header_test ("header.htk", SF_FORMAT_HTK) ;
202		update_seek_short_test ("header_short.htk", SF_FORMAT_HTK) ;
203		test_count++ ;
204		} ;
205
206	if (do_all || ! strcmp (argv [1], "svx"))
207	{	update_header_test ("header.svx", SF_FORMAT_SVX) ;
208		update_seek_short_test ("header_short.svx", SF_FORMAT_SVX) ;
209		test_count++ ;
210		} ;
211
212	if (do_all || ! strcmp (argv [1], "voc"))
213	{	update_header_test ("header.voc", SF_FORMAT_VOC) ;
214		/*-update_seek_short_test ("header_short.voc", SF_FORMAT_VOC) ;-*/
215		test_count++ ;
216		} ;
217
218	if (do_all || ! strcmp (argv [1], "sds"))
219	{	update_header_test ("header.sds", SF_FORMAT_SDS) ;
220		/*-update_seek_short_test ("header_short.sds", SF_FORMAT_SDS) ;-*/
221		test_count++ ;
222		} ;
223
224	if (do_all || ! strcmp (argv [1], "mpc2k"))
225	{	update_header_test ("header.mpc", SF_FORMAT_MPC2K) ;
226		update_seek_short_test ("header_short.mpc", SF_FORMAT_MPC2K) ;
227		test_count++ ;
228		} ;
229
230	if (do_all || ! strcmp (argv [1], "flac"))
231	{	if (HAVE_EXTERNAL_XIPH_LIBS)
232			update_header_before_write_test ("header.flac", SF_FORMAT_FLAC) ;
233		else
234			puts ("    No FLAC tests because FLAC support was not compiled in.") ;
235		test_count++ ;
236		} ;
237
238	if (test_count == 0)
239	{	printf ("Mono : ************************************\n") ;
240		printf ("Mono : *  No '%s' test defined.\n", argv [1]) ;
241		printf ("Mono : ************************************\n") ;
242		return 1 ;
243		} ;
244
245	return 0 ;
246} /* main */
247
248
249/*============================================================================================
250**	Here are the test functions.
251*/
252
253static void
254update_header_sub (const char *filename, int typemajor, int write_mode)
255{	SNDFILE		*outfile, *infile ;
256	SF_INFO		sfinfo ;
257	int			k ;
258
259	memset (&sfinfo, 0, sizeof (sfinfo)) ;
260	sfinfo.samplerate = 44100 ;
261	sfinfo.format = (typemajor | SF_FORMAT_PCM_16) ;
262	sfinfo.channels = 1 ;
263
264	outfile = test_open_file_or_die (filename, write_mode, &sfinfo, SF_TRUE, __LINE__) ;
265
266	for (k = 0 ; k < BUFFER_LEN ; k++)
267		data_out [k] = k + 1 ;
268	test_write_int_or_die (outfile, 0, data_out, BUFFER_LEN, __LINE__) ;
269
270	if (typemajor != SF_FORMAT_HTK)
271	{	/* The HTK header is not correct when the file is first written. */
272		infile = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
273		sf_close (infile) ;
274		} ;
275
276	sf_command (outfile, SFC_UPDATE_HEADER_NOW, NULL, 0) ;
277
278	/*
279	** Open file and check log buffer for an error. If header update failed
280	** the the log buffer will contain errors.
281	*/
282	infile = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
283	check_log_buffer_or_die (infile, __LINE__) ;
284
285	if (sfinfo.frames < BUFFER_LEN || sfinfo.frames > BUFFER_LEN + 50)
286	{	printf ("\n\nLine %d : Incorrect sample count (%" PRId64 " should be %d)\n", __LINE__, sfinfo.frames, BUFFER_LEN) ;
287		dump_log_buffer (infile) ;
288		exit (1) ;
289		} ;
290
291	test_read_int_or_die (infile, 0, data_in, BUFFER_LEN, __LINE__) ;
292	for (k = 0 ; k < BUFFER_LEN ; k++)
293		if (data_out [k] != k + 1)
294			printf ("Error : line %d\n", __LINE__) ;
295
296	sf_close (infile) ;
297
298	/* Set auto update on. */
299	sf_command (outfile, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE) ;
300
301	/* Write more data_out. */
302	for (k = 0 ; k < BUFFER_LEN ; k++)
303		data_out [k] = k + 2 ;
304	test_write_int_or_die (outfile, 0, data_out, BUFFER_LEN, __LINE__) ;
305
306	/* Open file again and make sure no errors in log buffer. */
307	infile = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
308	check_log_buffer_or_die (infile, __LINE__) ;
309
310	if (sfinfo.frames < 2 * BUFFER_LEN || sfinfo.frames > 2 * BUFFER_LEN + 50)
311	{	printf ("\n\nLine %d : Incorrect sample count (%" PRId64 " should be %d)\n", __LINE__, sfinfo.frames, 2 * BUFFER_LEN) ;
312		dump_log_buffer (infile) ;
313		exit (1) ;
314		} ;
315
316	sf_close (infile) ;
317
318	sf_close (outfile) ;
319
320	unlink (filename) ;
321} /* update_header_sub */
322
323static void
324update_header_test (const char *filename, int typemajor)
325{
326	print_test_name ("update_header_test", filename) ;
327
328	update_header_sub (filename, typemajor, SFM_WRITE) ;
329	update_header_sub (filename, typemajor, SFM_RDWR) ;
330
331	unlink (filename) ;
332	puts ("ok") ;
333} /* update_header_test */
334
335static void
336update_header_before_write_test (const char *filename, int typemajor)
337{
338	SNDFILE		*outfile ;
339	SF_INFO		sfinfo ;
340	int			k ;
341
342	print_test_name ("update_header_before_write", filename) ;
343
344	memset (&sfinfo, 0, sizeof (sfinfo)) ;
345	sfinfo.samplerate = 44100 ;
346	sfinfo.format = (typemajor | SF_FORMAT_PCM_16) ;
347	sfinfo.channels = 1 ;
348
349	outfile = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
350
351	/* FLAC can only write the header once; if the first call to sf_write() will
352	** also attempt to write the header, it fails. FLAC-specific regression
353	*/
354	sf_command (outfile, SFC_UPDATE_HEADER_NOW, NULL, 0) ;
355
356	for (k = 0 ; k < BUFFER_LEN ; k++)
357		data_out [k] = k + 1 ;
358	test_write_int_or_die (outfile, 0, data_out, BUFFER_LEN, __LINE__) ;
359
360	sf_close (outfile) ;
361	unlink (filename) ;
362	puts ("ok") ;
363} /* update_header_before_write_test */
364
365/*==============================================================================
366*/
367
368[+ FOR data_type
369+]static void
370update_seek_[+ (get "name") +]_test	(const char *filename, int filetype)
371{	SNDFILE *outfile, *infile ;
372	SF_INFO sfinfo ;
373	sf_count_t frames ;
374	[+ (get "name") +] buffer [8] ;
375	int k ;
376
377	print_test_name ("update_seek_[+ (get "name") +]_test", filename) ;
378
379	memset (buffer, 0, sizeof (buffer)) ;
380
381	/* Create sound outfile with no data. */
382	memset (&sfinfo, 0, sizeof (sfinfo)) ;
383	sfinfo.format = filetype | [+ (get "format") +] ;
384	sfinfo.samplerate = 48000 ;
385	sfinfo.channels = 2 ;
386
387	if (sf_format_check (&sfinfo) == SF_FALSE)
388		sfinfo.channels = 1 ;
389
390	outfile = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ;
391	sf_close (outfile) ;
392
393	/* Open again for read/write. */
394	outfile = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_TRUE, __LINE__) ;
395
396	/*
397	** In auto header update mode, seeking to the end of the file with
398	** SEEK_SET will fail from the 2nd seek on.  seeking to 0, SEEK_END
399	** will seek to 0 anyway
400	*/
401	if (sf_command (outfile, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE) == 0)
402	{	printf ("\n\nError : sf_command (SFC_SET_UPDATE_HEADER_AUTO) return error : %s\n\n", sf_strerror (outfile)) ;
403		exit (1) ;
404		} ;
405
406	/* Now write some frames. */
407	frames = ARRAY_LEN (buffer) / sfinfo.channels ;
408
409	for (k = 0 ; k < 6 ; k++)
410	{	test_seek_or_die (outfile, k * frames, SEEK_SET, k * frames, sfinfo.channels, __LINE__) ;
411		test_seek_or_die (outfile, 0, SEEK_END, k * frames, sfinfo.channels, __LINE__) ;
412
413		/* Open file again and make sure no errors in log buffer. */
414		infile = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ;
415		check_log_buffer_or_die (infile, __LINE__) ;
416		sf_close (infile) ;
417
418		if (sfinfo.frames != k * frames)
419		{	printf ("\n\nLine %d : Incorrect sample count (%" PRId64 " should be %" PRId64 ")\n", __LINE__, sfinfo.frames, k + frames) ;
420			dump_log_buffer (infile) ;
421			exit (1) ;
422			} ;
423
424		if ((k & 1) == 0)
425			test_write_[+ (get "name") +]_or_die (outfile, k, buffer, sfinfo.channels * frames, __LINE__) ;
426		else
427			test_writef_[+ (get "name") +]_or_die (outfile, k, buffer, frames, __LINE__) ;
428		} ;
429
430	sf_close (outfile) ;
431	unlink (filename) ;
432
433	puts ("ok") ;
434	return ;
435} /* update_seek_[+ (get "name") +]_test */
436
437[+ ENDFOR data_type
438+]
439
440static void
441header_shrink_test (const char *filename, int filetype)
442{	SNDFILE *outfile, *infile ;
443	SF_INFO sfinfo ;
444	sf_count_t frames ;
445	float buffer [8], bufferin [8] ;
446
447	print_test_name ("header_shrink_test", filename) ;
448
449	memset (&sfinfo, 0, sizeof (sfinfo)) ;
450	sfinfo.samplerate = 44100 ;
451	sfinfo.format = filetype | SF_FORMAT_FLOAT ;
452	sfinfo.channels = 1 ;
453
454	memset (buffer, 0xA0, sizeof (buffer)) ;
455
456	/* Now write some frames. */
457	frames = ARRAY_LEN (buffer) / sfinfo.channels ;
458
459	/* Test the file with extra header data. */
460	outfile = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
461
462	sf_command (outfile, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_TRUE) ;
463	sf_command (outfile, SFC_UPDATE_HEADER_NOW, NULL, SF_FALSE) ;
464	sf_command (outfile, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_FALSE) ;
465
466	test_writef_float_or_die (outfile, 0, buffer, frames, __LINE__) ;
467	sf_close (outfile) ;
468
469	/* Open again for read. */
470	infile = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
471
472	test_readf_float_or_die (infile, 0, bufferin, frames, __LINE__) ;
473	sf_close (infile) ;
474
475	compare_float_or_die (buffer, bufferin, frames, __LINE__) ;
476
477	unlink (filename) ;
478	puts ("ok") ;
479	return ;
480} /* header_shrink_test */
481
482
483static void
484extra_header_test (const char *filename, int filetype)
485{	SNDFILE *outfile, *infile ;
486	SF_INFO sfinfo ;
487	sf_count_t frames ;
488	short buffer [8] ;
489	int k = 0 ;
490
491	print_test_name ("extra_header_test", filename) ;
492
493	memset (&sfinfo, 0, sizeof (sfinfo)) ;
494	sfinfo.samplerate = 44100 ;
495	sfinfo.format = (filetype | SF_FORMAT_PCM_16) ;
496	sfinfo.channels = 1 ;
497
498	memset (buffer, 0xA0, sizeof (buffer)) ;
499
500	/* Now write some frames. */
501	frames = ARRAY_LEN (buffer) / sfinfo.channels ;
502
503	/* Test the file with extra header data. */
504	outfile = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, [+ (tpl-file-line "%2$d") +]) ;
505	sf_set_string (outfile, SF_STR_TITLE, filename) ;
506	test_writef_short_or_die (outfile, k, buffer, frames, [+ (tpl-file-line "%2$d") +]) ;
507	sf_set_string (outfile, SF_STR_COPYRIGHT, "(c) 1980 Erik") ;
508	sf_close (outfile) ;
509
510#if 1
511	/*
512	**  Erik de Castro Lopo <erikd@mega-nerd.com> May 23 2004.
513	**
514	** This file has extra string data in the header and therefore cannot
515	** currently be opened in SFM_RDWR mode. This is fixable, but its in
516	** a part of the code I don't want to fiddle with until the Ogg/Vorbis
517	** integration is done.
518	*/
519
520	if ((infile = sf_open (filename, SFM_RDWR, &sfinfo)) != NULL)
521	{	printf ("\n\nError : should not be able to open this file in SFM_RDWR.\n\n") ;
522		exit (1) ;
523		} ;
524
525	unlink (filename) ;
526	puts ("ok") ;
527	return ;
528#else
529
530	hexdump_file (filename, 0, 100000) ;
531
532	/* Open again for read/write. */
533	outfile = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, [+ (tpl-file-line "%2$d") +]) ;
534
535	/*
536	** In auto header update mode, seeking to the end of the file with
537	** SEEK_SET will fail from the 2nd seek on.  seeking to 0, SEEK_END
538	** will seek to 0 anyway
539	*/
540	if (sf_command (outfile, SFC_SET_UPDATE_HEADER_AUTO, NULL, SF_TRUE) == 0)
541	{	printf ("\n\nError : sf_command (SFC_SET_UPDATE_HEADER_AUTO) return error : %s\n\n", sf_strerror (outfile)) ;
542		exit (1) ;
543		} ;
544
545	/* Now write some frames. */
546	frames = ARRAY_LEN (buffer) / sfinfo.channels ;
547
548	for (k = 1 ; k < 6 ; k++)
549	{
550		printf ("\n*** pass %d\n", k) ;
551		memset (buffer, 0xA0 + k, sizeof (buffer)) ;
552
553
554		test_seek_or_die (outfile, k * frames, SEEK_SET, k * frames, sfinfo.channels, [+ (tpl-file-line "%2$d") +]) ;
555		test_seek_or_die (outfile, 0, SEEK_END, k * frames, sfinfo.channels, [+ (tpl-file-line "%2$d") +]) ;
556
557		/* Open file again and make sure no errors in log buffer. */
558		if (0)
559		{	infile = test_open_file_or_die (filename, SFM_READ, &sfinfo, [+ (tpl-file-line "%2$d") +]) ;
560			check_log_buffer_or_die (infile, [+ (tpl-file-line "%2$d") +]) ;
561			sf_close (infile) ;
562			} ;
563
564		if (sfinfo.frames != k * frames)
565		{	printf ("\n\nLine %d : Incorrect sample count (%" PRId64 " should be %" PRId64 ")\n", [+ (tpl-file-line "%2$d") +], sfinfo.frames, k + frames) ;
566			dump_log_buffer (infile) ;
567			exit (1) ;
568			} ;
569
570		if ((k & 1) == 0)
571			test_write_short_or_die (outfile, k, buffer, sfinfo.channels * frames, [+ (tpl-file-line "%2$d") +]) ;
572		else
573			test_writef_short_or_die (outfile, k, buffer, frames, [+ (tpl-file-line "%2$d") +]) ;
574		hexdump_file (filename, 0, 100000) ;
575		} ;
576
577	sf_close (outfile) ;
578	unlink (filename) ;
579
580	puts ("ok") ;
581	return ;
582#endif
583} /* extra_header_test */
584