1b815c7f3Sopenharmony_ci/*
2b815c7f3Sopenharmony_ci** Copyright (C) 2001-2016 Erik de Castro Lopo <erikd@mega-nerd.com>
3b815c7f3Sopenharmony_ci**
4b815c7f3Sopenharmony_ci** This program is free software; you can redistribute it and/or modify
5b815c7f3Sopenharmony_ci** it under the terms of the GNU General Public License as published by
6b815c7f3Sopenharmony_ci** the Free Software Foundation; either version 2 of the License, or
7b815c7f3Sopenharmony_ci** (at your option) any later version.
8b815c7f3Sopenharmony_ci**
9b815c7f3Sopenharmony_ci** This program is distributed in the hope that it will be useful,
10b815c7f3Sopenharmony_ci** but WITHOUT ANY WARRANTY; without even the implied warranty of
11b815c7f3Sopenharmony_ci** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12b815c7f3Sopenharmony_ci** GNU General Public License for more details.
13b815c7f3Sopenharmony_ci**
14b815c7f3Sopenharmony_ci** You should have received a copy of the GNU General Public License
15b815c7f3Sopenharmony_ci** along with this program; if not, write to the Free Software
16b815c7f3Sopenharmony_ci** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17b815c7f3Sopenharmony_ci*/
18b815c7f3Sopenharmony_ci
19b815c7f3Sopenharmony_ci#include "sfconfig.h"
20b815c7f3Sopenharmony_ci
21b815c7f3Sopenharmony_ci#include <stdio.h>
22b815c7f3Sopenharmony_ci#include <stdlib.h>
23b815c7f3Sopenharmony_ci#include <string.h>
24b815c7f3Sopenharmony_ci#include <math.h>
25b815c7f3Sopenharmony_ci#include <inttypes.h>
26b815c7f3Sopenharmony_ci
27b815c7f3Sopenharmony_ci#if HAVE_UNISTD_H
28b815c7f3Sopenharmony_ci#include <unistd.h>
29b815c7f3Sopenharmony_ci#else
30b815c7f3Sopenharmony_ci#include "sf_unistd.h"
31b815c7f3Sopenharmony_ci#endif
32b815c7f3Sopenharmony_ci
33b815c7f3Sopenharmony_ci#include <sndfile.h>
34b815c7f3Sopenharmony_ci
35b815c7f3Sopenharmony_ci#include "utils.h"
36b815c7f3Sopenharmony_ci
37b815c7f3Sopenharmony_ci#define	BUFFER_LEN		(1 << 15)
38b815c7f3Sopenharmony_ci#define LOG_BUFFER_SIZE	1024
39b815c7f3Sopenharmony_ci
40b815c7f3Sopenharmony_ci
41b815c7f3Sopenharmony_cistatic	void	test_float_peak	(const char *filename, int filetype) ;
42b815c7f3Sopenharmony_cistatic	void	read_write_peak_test	(const char *filename, int filetype) ;
43b815c7f3Sopenharmony_ci
44b815c7f3Sopenharmony_cistatic void		check_logged_peaks (char *buffer) ;
45b815c7f3Sopenharmony_ci
46b815c7f3Sopenharmony_ci/* Force the start of this buffer to be double aligned. Sparc-solaris will
47b815c7f3Sopenharmony_ci** choke if its not.
48b815c7f3Sopenharmony_ci*/
49b815c7f3Sopenharmony_cistatic	double	data [BUFFER_LEN] ;
50b815c7f3Sopenharmony_cistatic	char	log_buffer [LOG_BUFFER_SIZE] ;
51b815c7f3Sopenharmony_ci
52b815c7f3Sopenharmony_ciint
53b815c7f3Sopenharmony_cimain (int argc, char *argv [])
54b815c7f3Sopenharmony_ci{	int		do_all = 0 ;
55b815c7f3Sopenharmony_ci	int		test_count = 0 ;
56b815c7f3Sopenharmony_ci
57b815c7f3Sopenharmony_ci	if (argc != 2)
58b815c7f3Sopenharmony_ci	{	printf ("Usage : %s <test>\n", argv [0]) ;
59b815c7f3Sopenharmony_ci		printf ("    Where <test> is one of the following:\n") ;
60b815c7f3Sopenharmony_ci		printf ("           aiff - test AIFF file PEAK chunk\n") ;
61b815c7f3Sopenharmony_ci		printf ("           caf  - test CAF file PEAK chunk\n") ;
62b815c7f3Sopenharmony_ci		printf ("           wav  - test WAV file peak chunk\n") ;
63b815c7f3Sopenharmony_ci		printf ("           all  - perform all tests\n") ;
64b815c7f3Sopenharmony_ci		exit (1) ;
65b815c7f3Sopenharmony_ci		} ;
66b815c7f3Sopenharmony_ci
67b815c7f3Sopenharmony_ci	do_all = ! strcmp (argv [1], "all") ;
68b815c7f3Sopenharmony_ci
69b815c7f3Sopenharmony_ci	if (do_all || ! strcmp (argv [1], "wav"))
70b815c7f3Sopenharmony_ci	{	test_float_peak ("peak_float.wav", SF_FORMAT_WAV | SF_FORMAT_FLOAT) ;
71b815c7f3Sopenharmony_ci		test_float_peak ("peak_float.wavex", SF_FORMAT_WAVEX | SF_FORMAT_FLOAT) ;
72b815c7f3Sopenharmony_ci		test_float_peak ("peak_float.rifx", SF_ENDIAN_BIG | SF_FORMAT_WAV | SF_FORMAT_FLOAT) ;
73b815c7f3Sopenharmony_ci
74b815c7f3Sopenharmony_ci		read_write_peak_test ("rw_peak.wav", SF_FORMAT_WAV | SF_FORMAT_FLOAT) ;
75b815c7f3Sopenharmony_ci		read_write_peak_test ("rw_peak.wavex", SF_FORMAT_WAVEX | SF_FORMAT_FLOAT) ;
76b815c7f3Sopenharmony_ci		test_count++ ;
77b815c7f3Sopenharmony_ci		} ;
78b815c7f3Sopenharmony_ci
79b815c7f3Sopenharmony_ci	if (do_all || ! strcmp (argv [1], "aiff"))
80b815c7f3Sopenharmony_ci	{	test_float_peak	("peak_float.aiff", SF_FORMAT_AIFF | SF_FORMAT_FLOAT) ;
81b815c7f3Sopenharmony_ci
82b815c7f3Sopenharmony_ci		read_write_peak_test ("rw_peak.aiff", SF_FORMAT_AIFF | SF_FORMAT_FLOAT) ;
83b815c7f3Sopenharmony_ci		test_count++ ;
84b815c7f3Sopenharmony_ci		} ;
85b815c7f3Sopenharmony_ci
86b815c7f3Sopenharmony_ci	if (do_all || ! strcmp (argv [1], "caf"))
87b815c7f3Sopenharmony_ci	{	test_float_peak	("peak_float.caf", SF_FORMAT_CAF | SF_FORMAT_FLOAT) ;
88b815c7f3Sopenharmony_ci
89b815c7f3Sopenharmony_ci		read_write_peak_test ("rw_peak.caf", SF_FORMAT_CAF | SF_FORMAT_FLOAT) ;
90b815c7f3Sopenharmony_ci		test_count++ ;
91b815c7f3Sopenharmony_ci		} ;
92b815c7f3Sopenharmony_ci
93b815c7f3Sopenharmony_ci	if (do_all || ! strcmp (argv [1], "rf64"))
94b815c7f3Sopenharmony_ci	{	test_float_peak	("peak_float.rf64", SF_FORMAT_RF64 | SF_FORMAT_FLOAT) ;
95b815c7f3Sopenharmony_ci
96b815c7f3Sopenharmony_ci		read_write_peak_test ("rw_peak.rf64", SF_FORMAT_RF64 | SF_FORMAT_FLOAT) ;
97b815c7f3Sopenharmony_ci		test_count++ ;
98b815c7f3Sopenharmony_ci		} ;
99b815c7f3Sopenharmony_ci
100b815c7f3Sopenharmony_ci	if (test_count == 0)
101b815c7f3Sopenharmony_ci	{	printf ("Mono : ************************************\n") ;
102b815c7f3Sopenharmony_ci		printf ("Mono : *  No '%s' test defined.\n", argv [1]) ;
103b815c7f3Sopenharmony_ci		printf ("Mono : ************************************\n") ;
104b815c7f3Sopenharmony_ci		return 1 ;
105b815c7f3Sopenharmony_ci		} ;
106b815c7f3Sopenharmony_ci
107b815c7f3Sopenharmony_ci	return 0 ;
108b815c7f3Sopenharmony_ci} /* main */
109b815c7f3Sopenharmony_ci
110b815c7f3Sopenharmony_ci/*============================================================================================
111b815c7f3Sopenharmony_ci**	Here are the test functions.
112b815c7f3Sopenharmony_ci*/
113b815c7f3Sopenharmony_ci
114b815c7f3Sopenharmony_cistatic void
115b815c7f3Sopenharmony_citest_float_peak (const char *filename, int filetype)
116b815c7f3Sopenharmony_ci{	SNDFILE		*file ;
117b815c7f3Sopenharmony_ci	SF_INFO		sfinfo ;
118b815c7f3Sopenharmony_ci	int			k, frames, count ;
119b815c7f3Sopenharmony_ci
120b815c7f3Sopenharmony_ci	print_test_name ("test_float_peak", filename) ;
121b815c7f3Sopenharmony_ci
122b815c7f3Sopenharmony_ci	memset (&sfinfo, 0, sizeof (sfinfo)) ;
123b815c7f3Sopenharmony_ci	sfinfo.samplerate	= 44100 ;
124b815c7f3Sopenharmony_ci	sfinfo.format		= filetype ;
125b815c7f3Sopenharmony_ci	sfinfo.channels		= 4 ;
126b815c7f3Sopenharmony_ci	sfinfo.frames		= 0 ;
127b815c7f3Sopenharmony_ci
128b815c7f3Sopenharmony_ci	frames = BUFFER_LEN / sfinfo.channels ;
129b815c7f3Sopenharmony_ci
130b815c7f3Sopenharmony_ci	/* Create some random data with a peak value of 0.66. */
131b815c7f3Sopenharmony_ci	for (k = 0 ; k < BUFFER_LEN ; k++)
132b815c7f3Sopenharmony_ci		data [k] = (rand () % 2000) / 3000.0 ;
133b815c7f3Sopenharmony_ci
134b815c7f3Sopenharmony_ci	/* Insert some larger peaks a know locations. */
135b815c7f3Sopenharmony_ci	data [4 * (frames / 8) + 0] = (frames / 8) * 0.01 ;	/* First channel */
136b815c7f3Sopenharmony_ci	data [4 * (frames / 6) + 1] = (frames / 6) * 0.01 ;	/* Second channel */
137b815c7f3Sopenharmony_ci	data [4 * (frames / 4) + 2] = (frames / 4) * 0.01 ;	/* Third channel */
138b815c7f3Sopenharmony_ci	data [4 * (frames / 2) + 3] = (frames / 2) * 0.01 ;	/* Fourth channel */
139b815c7f3Sopenharmony_ci
140b815c7f3Sopenharmony_ci	/* Write a file with PEAK chunks. */
141b815c7f3Sopenharmony_ci	file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, 0, __LINE__) ;
142b815c7f3Sopenharmony_ci
143b815c7f3Sopenharmony_ci	/* Try to confuse the header writer by adding a removing the PEAK chunk. */
144b815c7f3Sopenharmony_ci	sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_TRUE) ;
145b815c7f3Sopenharmony_ci	sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_FALSE) ;
146b815c7f3Sopenharmony_ci	sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_TRUE) ;
147b815c7f3Sopenharmony_ci
148b815c7f3Sopenharmony_ci	/*	Write the data in four passed. The data is designed so that peaks will
149b815c7f3Sopenharmony_ci	**	be written in the different calls to sf_write_double ().
150b815c7f3Sopenharmony_ci	*/
151b815c7f3Sopenharmony_ci	for (count = 0 ; count < 4 ; count ++)
152b815c7f3Sopenharmony_ci		test_write_double_or_die (file, 0, data + count * BUFFER_LEN / 4, BUFFER_LEN / 4, BUFFER_LEN / 4) ;
153b815c7f3Sopenharmony_ci
154b815c7f3Sopenharmony_ci	sf_close (file) ;
155b815c7f3Sopenharmony_ci
156b815c7f3Sopenharmony_ci	file = test_open_file_or_die (filename, SFM_READ, &sfinfo, 0, __LINE__) ;
157b815c7f3Sopenharmony_ci
158b815c7f3Sopenharmony_ci	if (sfinfo.format != filetype)
159b815c7f3Sopenharmony_ci	{	printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__, filetype, sfinfo.format) ;
160b815c7f3Sopenharmony_ci		exit (1) ;
161b815c7f3Sopenharmony_ci		} ;
162b815c7f3Sopenharmony_ci
163b815c7f3Sopenharmony_ci	if (sfinfo.frames != frames)
164b815c7f3Sopenharmony_ci	{	printf ("\n\nLine %d: Incorrect number of frames in file. (%d => %ld)\n", __LINE__, frames, (long) sfinfo.frames) ;
165b815c7f3Sopenharmony_ci		exit (1) ;
166b815c7f3Sopenharmony_ci		} ;
167b815c7f3Sopenharmony_ci
168b815c7f3Sopenharmony_ci	if (sfinfo.channels != 4)
169b815c7f3Sopenharmony_ci	{	printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__) ;
170b815c7f3Sopenharmony_ci		exit (1) ;
171b815c7f3Sopenharmony_ci		} ;
172b815c7f3Sopenharmony_ci
173b815c7f3Sopenharmony_ci	/* Check these two commands. */
174b815c7f3Sopenharmony_ci	if (sf_command (file, SFC_GET_SIGNAL_MAX, data, sizeof (double)) == SF_FALSE)
175b815c7f3Sopenharmony_ci	{	printf ("\n\nLine %d: Command should have returned SF_TRUE.\n", __LINE__) ;
176b815c7f3Sopenharmony_ci		exit (1) ;
177b815c7f3Sopenharmony_ci		} ;
178b815c7f3Sopenharmony_ci
179b815c7f3Sopenharmony_ci	if (fabs (data [0] - (frames / 2) * 0.01) > 0.01)
180b815c7f3Sopenharmony_ci	{	printf ("\n\nLine %d: Bad peak value (%f should be %f) for command SFC_GET_SIGNAL_MAX.\n", __LINE__, data [0], (frames / 2) * 0.01) ;
181b815c7f3Sopenharmony_ci		exit (1) ;
182b815c7f3Sopenharmony_ci		} ;
183b815c7f3Sopenharmony_ci
184b815c7f3Sopenharmony_ci	if (sf_command (file, SFC_GET_MAX_ALL_CHANNELS, data, sizeof (double) * sfinfo.channels) == SF_FALSE)
185b815c7f3Sopenharmony_ci	{	printf ("\n\nLine %d: Command should have returned SF_TRUE.\n", __LINE__) ;
186b815c7f3Sopenharmony_ci		exit (1) ;
187b815c7f3Sopenharmony_ci		} ;
188b815c7f3Sopenharmony_ci
189b815c7f3Sopenharmony_ci	if (fabs (data [3] - (frames / 2) * 0.01) > 0.01)
190b815c7f3Sopenharmony_ci	{	printf ("\n\nLine %d: Bad peak value (%f should be %f) for command SFC_GET_MAX_ALL_CHANNELS.\n", __LINE__, data [0], (frames / 2) * 0.01) ;
191b815c7f3Sopenharmony_ci		exit (1) ;
192b815c7f3Sopenharmony_ci		} ;
193b815c7f3Sopenharmony_ci
194b815c7f3Sopenharmony_ci	/* Get the log buffer data. */
195b815c7f3Sopenharmony_ci	log_buffer [0] = 0 ;
196b815c7f3Sopenharmony_ci	sf_command	(file, SFC_GET_LOG_INFO, log_buffer, LOG_BUFFER_SIZE) ;
197b815c7f3Sopenharmony_ci
198b815c7f3Sopenharmony_ci	if (strlen (log_buffer) == 0)
199b815c7f3Sopenharmony_ci	{	printf ("\n\nLine %d: Empty log buffer,\n", __LINE__) ;
200b815c7f3Sopenharmony_ci		exit (1) ;
201b815c7f3Sopenharmony_ci		} ;
202b815c7f3Sopenharmony_ci
203b815c7f3Sopenharmony_ci	check_logged_peaks (log_buffer) ;
204b815c7f3Sopenharmony_ci
205b815c7f3Sopenharmony_ci	sf_close (file) ;
206b815c7f3Sopenharmony_ci
207b815c7f3Sopenharmony_ci	/* Write a file ***without*** PEAK chunks. */
208b815c7f3Sopenharmony_ci	file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, 0, __LINE__) ;
209b815c7f3Sopenharmony_ci
210b815c7f3Sopenharmony_ci	/* Try to confuse the header writer by adding a removing the PEAK chunk. */
211b815c7f3Sopenharmony_ci	sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_FALSE) ;
212b815c7f3Sopenharmony_ci	sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_TRUE) ;
213b815c7f3Sopenharmony_ci	sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_FALSE) ;
214b815c7f3Sopenharmony_ci
215b815c7f3Sopenharmony_ci	/*	Write the data in four passed. The data is designed so that peaks will
216b815c7f3Sopenharmony_ci	**	be written in the different calls to sf_write_double ().
217b815c7f3Sopenharmony_ci	*/
218b815c7f3Sopenharmony_ci	for (count = 0 ; count < 4 ; count ++)
219b815c7f3Sopenharmony_ci		test_write_double_or_die (file, 0, data + count * BUFFER_LEN / 4, BUFFER_LEN / 4, BUFFER_LEN / 4) ;
220b815c7f3Sopenharmony_ci
221b815c7f3Sopenharmony_ci	sf_close (file) ;
222b815c7f3Sopenharmony_ci
223b815c7f3Sopenharmony_ci	file = test_open_file_or_die (filename, SFM_READ, &sfinfo, 0, __LINE__) ;
224b815c7f3Sopenharmony_ci
225b815c7f3Sopenharmony_ci	/* Check these two commands. */
226b815c7f3Sopenharmony_ci	if (sf_command (file, SFC_GET_SIGNAL_MAX, data, sizeof (double)))
227b815c7f3Sopenharmony_ci	{	printf ("\n\nLine %d: Command should have returned SF_FALSE.\n", __LINE__) ;
228b815c7f3Sopenharmony_ci		exit (1) ;
229b815c7f3Sopenharmony_ci		} ;
230b815c7f3Sopenharmony_ci
231b815c7f3Sopenharmony_ci	if (sf_command (file, SFC_GET_MAX_ALL_CHANNELS, data, sizeof (double) * sfinfo.channels))
232b815c7f3Sopenharmony_ci	{	printf ("\n\nLine %d: Command should have returned SF_FALSE.\n", __LINE__) ;
233b815c7f3Sopenharmony_ci		exit (1) ;
234b815c7f3Sopenharmony_ci		} ;
235b815c7f3Sopenharmony_ci
236b815c7f3Sopenharmony_ci	/* Get the log buffer data. */
237b815c7f3Sopenharmony_ci	log_buffer [0] = 0 ;
238b815c7f3Sopenharmony_ci	sf_command	(file, SFC_GET_LOG_INFO, log_buffer, LOG_BUFFER_SIZE) ;
239b815c7f3Sopenharmony_ci
240b815c7f3Sopenharmony_ci	if (strlen (log_buffer) == 0)
241b815c7f3Sopenharmony_ci	{	printf ("\n\nLine %d: Empty log buffer,\n", __LINE__) ;
242b815c7f3Sopenharmony_ci		exit (1) ;
243b815c7f3Sopenharmony_ci		} ;
244b815c7f3Sopenharmony_ci
245b815c7f3Sopenharmony_ci	if (strstr (log_buffer, "PEAK :") != NULL)
246b815c7f3Sopenharmony_ci	{	printf ("\n\nLine %d: Should not have a PEAK chunk in this file.\n\n", __LINE__) ;
247b815c7f3Sopenharmony_ci		puts (log_buffer) ;
248b815c7f3Sopenharmony_ci		exit (1) ;
249b815c7f3Sopenharmony_ci		} ;
250b815c7f3Sopenharmony_ci
251b815c7f3Sopenharmony_ci	sf_close (file) ;
252b815c7f3Sopenharmony_ci
253b815c7f3Sopenharmony_ci	unlink (filename) ;
254b815c7f3Sopenharmony_ci	printf ("ok\n") ;
255b815c7f3Sopenharmony_ci} /* test_float_peak */
256b815c7f3Sopenharmony_ci
257b815c7f3Sopenharmony_cistatic void
258b815c7f3Sopenharmony_cicheck_logged_peaks (char *buffer)
259b815c7f3Sopenharmony_ci{	char 	*cptr ;
260b815c7f3Sopenharmony_ci	int		k, chan, channel_count, position ;
261b815c7f3Sopenharmony_ci	float	value ;
262b815c7f3Sopenharmony_ci
263b815c7f3Sopenharmony_ci	if (strstr (buffer, "should") || strstr (buffer, "*"))
264b815c7f3Sopenharmony_ci	{	printf ("\n\nLine %d: Something wrong in buffer. Dumping.\n", __LINE__) ;
265b815c7f3Sopenharmony_ci		puts (buffer) ;
266b815c7f3Sopenharmony_ci		exit (1) ;
267b815c7f3Sopenharmony_ci		} ;
268b815c7f3Sopenharmony_ci
269b815c7f3Sopenharmony_ci	channel_count = 0 ;
270b815c7f3Sopenharmony_ci	cptr = strstr (buffer, "Channels") ;
271b815c7f3Sopenharmony_ci	if (cptr && sscanf (cptr, "Channels      : %d", &k) == 1)
272b815c7f3Sopenharmony_ci		channel_count = k ;
273b815c7f3Sopenharmony_ci	else if (cptr && sscanf (cptr, "Channels / frame : %d", &k) == 1)
274b815c7f3Sopenharmony_ci		channel_count = k ;
275b815c7f3Sopenharmony_ci	else
276b815c7f3Sopenharmony_ci	{	printf ("\n\nLine %d: Couldn't find channel count.\n", __LINE__) ;
277b815c7f3Sopenharmony_ci		exit (1) ;
278b815c7f3Sopenharmony_ci		} ;
279b815c7f3Sopenharmony_ci
280b815c7f3Sopenharmony_ci	if (channel_count != 4)
281b815c7f3Sopenharmony_ci	{	printf ("\n\nLine %d: Wrong channel count (4 ->%d).\n", __LINE__, channel_count) ;
282b815c7f3Sopenharmony_ci		exit (1) ;
283b815c7f3Sopenharmony_ci		} ;
284b815c7f3Sopenharmony_ci
285b815c7f3Sopenharmony_ci	if (! (cptr = strstr (buffer, "Ch   Position       Value")))
286b815c7f3Sopenharmony_ci	{	printf ("\n\nLine %d: Can't find PEAK data.\n", __LINE__) ;
287b815c7f3Sopenharmony_ci		exit (1) ;
288b815c7f3Sopenharmony_ci		} ;
289b815c7f3Sopenharmony_ci
290b815c7f3Sopenharmony_ci	for (k = 0 ; k < channel_count ; k++)
291b815c7f3Sopenharmony_ci	{	if (! (cptr = strchr (cptr, '\n')))
292b815c7f3Sopenharmony_ci		{	printf ("\n\nLine %d: Got lost.\n", __LINE__) ;
293b815c7f3Sopenharmony_ci			exit (1) ;
294b815c7f3Sopenharmony_ci			} ;
295b815c7f3Sopenharmony_ci		if (sscanf (cptr, "%d %d %f", &chan, &position, &value) != 3)
296b815c7f3Sopenharmony_ci		{	printf ("\n\nLine %d: sscanf failed.\n", __LINE__) ;
297b815c7f3Sopenharmony_ci			exit (1) ;
298b815c7f3Sopenharmony_ci			} ;
299b815c7f3Sopenharmony_ci		if (position == 0)
300b815c7f3Sopenharmony_ci		{	printf ("\n\nLine %d: peak position for channel %d should not be at offset 0.\n", __LINE__, chan) ;
301b815c7f3Sopenharmony_ci			printf ("%s", buffer) ;
302b815c7f3Sopenharmony_ci			exit (1) ;
303b815c7f3Sopenharmony_ci			} ;
304b815c7f3Sopenharmony_ci		if (chan != k || fabs ((position) * 0.01 - value) > 1e-6)
305b815c7f3Sopenharmony_ci		{	printf ("\n\nLine %d: Error : peak value incorrect!\n", __LINE__) ;
306b815c7f3Sopenharmony_ci			printf ("%s", buffer) ;
307b815c7f3Sopenharmony_ci			printf ("\n\nLine %d: %d %f %f\n", __LINE__, chan, position * 0.01, value) ;
308b815c7f3Sopenharmony_ci			exit (1) ;
309b815c7f3Sopenharmony_ci			} ;
310b815c7f3Sopenharmony_ci		cptr ++ ; /* Move past current newline. */
311b815c7f3Sopenharmony_ci		} ;
312b815c7f3Sopenharmony_ci
313b815c7f3Sopenharmony_ci} /* check_logged_peaks */
314b815c7f3Sopenharmony_ci
315b815c7f3Sopenharmony_cistatic	void
316b815c7f3Sopenharmony_ciread_write_peak_test (const char *filename, int filetype)
317b815c7f3Sopenharmony_ci{	SNDFILE	*file ;
318b815c7f3Sopenharmony_ci	SF_INFO	sfinfo ;
319b815c7f3Sopenharmony_ci
320b815c7f3Sopenharmony_ci	double	small_data [10], max_peak = 0.0 ;
321b815c7f3Sopenharmony_ci	unsigned k ;
322b815c7f3Sopenharmony_ci
323b815c7f3Sopenharmony_ci	print_test_name (__func__, filename) ;
324b815c7f3Sopenharmony_ci
325b815c7f3Sopenharmony_ci	for (k = 0 ; k < ARRAY_LEN (small_data) ; k ++)
326b815c7f3Sopenharmony_ci		small_data [k] = 0.1 ;
327b815c7f3Sopenharmony_ci
328b815c7f3Sopenharmony_ci	sfinfo.samplerate	= 44100 ;
329b815c7f3Sopenharmony_ci	sfinfo.channels		= 2 ;
330b815c7f3Sopenharmony_ci	sfinfo.format		= filetype ;
331b815c7f3Sopenharmony_ci	sfinfo.frames		= 0 ;
332b815c7f3Sopenharmony_ci
333b815c7f3Sopenharmony_ci	/* Open the file, add peak chunk and write samples with value 0.1. */
334b815c7f3Sopenharmony_ci	file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_FALSE, __LINE__) ;
335b815c7f3Sopenharmony_ci
336b815c7f3Sopenharmony_ci	sf_command (file, SFC_SET_ADD_PEAK_CHUNK, NULL, SF_TRUE) ;
337b815c7f3Sopenharmony_ci
338b815c7f3Sopenharmony_ci	test_write_double_or_die (file, 0, small_data, ARRAY_LEN (small_data), __LINE__) ;
339b815c7f3Sopenharmony_ci
340b815c7f3Sopenharmony_ci	sf_close (file) ;
341b815c7f3Sopenharmony_ci
342b815c7f3Sopenharmony_ci	/* Open the fiel RDWR, write sample valied 1.25. */
343b815c7f3Sopenharmony_ci	file = test_open_file_or_die (filename, SFM_RDWR, &sfinfo, SF_FALSE, __LINE__) ;
344b815c7f3Sopenharmony_ci
345b815c7f3Sopenharmony_ci	for (k = 0 ; k < ARRAY_LEN (small_data) ; k ++)
346b815c7f3Sopenharmony_ci		small_data [k] = 1.0 ;
347b815c7f3Sopenharmony_ci
348b815c7f3Sopenharmony_ci	test_write_double_or_die (file, 0, small_data, ARRAY_LEN (small_data), __LINE__) ;
349b815c7f3Sopenharmony_ci
350b815c7f3Sopenharmony_ci	sf_command (file, SFC_GET_SIGNAL_MAX, &max_peak, sizeof (max_peak)) ;
351b815c7f3Sopenharmony_ci
352b815c7f3Sopenharmony_ci	sf_close (file) ;
353b815c7f3Sopenharmony_ci
354b815c7f3Sopenharmony_ci	exit_if_true (max_peak < 0.1, "\n\nLine %d : max peak (%5.3f) should not be 0.1.\n\n", __LINE__, max_peak) ;
355b815c7f3Sopenharmony_ci
356b815c7f3Sopenharmony_ci	/* Open the file and test the values written to the PEAK chunk. */
357b815c7f3Sopenharmony_ci	file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_FALSE, __LINE__) ;
358b815c7f3Sopenharmony_ci
359b815c7f3Sopenharmony_ci	exit_if_true (sfinfo.channels * sfinfo.frames != 2 * ARRAY_LEN (small_data),
360b815c7f3Sopenharmony_ci			"Line %d : frame count is %" PRId64 ", should be %zd\n", __LINE__, sfinfo.frames, 2 * ARRAY_LEN (small_data)) ;
361b815c7f3Sopenharmony_ci
362b815c7f3Sopenharmony_ci	sf_command (file, SFC_GET_SIGNAL_MAX, &max_peak, sizeof (double)) ;
363b815c7f3Sopenharmony_ci
364b815c7f3Sopenharmony_ci	sf_close (file) ;
365b815c7f3Sopenharmony_ci
366b815c7f3Sopenharmony_ci	exit_if_true (max_peak < 1.0, "\n\nLine %d : max peak (%5.3f) should be 1.0.\n\n", __LINE__, max_peak) ;
367b815c7f3Sopenharmony_ci
368b815c7f3Sopenharmony_ci	unlink (filename) ;
369b815c7f3Sopenharmony_ci	puts ("ok") ;
370b815c7f3Sopenharmony_ci} /* read_write_peak_test */
371b815c7f3Sopenharmony_ci
372