2 ** Copyright (C) 2001-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
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.
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.
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.
34 #define BUFFER_LEN (1<<15)
35 #define LOG_BUFFER_SIZE 1024
38 static void test_float_peak (const char *filename
, int filetype
) ;
39 static void read_write_peak_test (const char *filename
, int filetype
) ;
41 static void check_logged_peaks (char *buffer
) ;
43 /* Force the start of this buffer to be double aligned. Sparc-solaris will
46 static double data
[BUFFER_LEN
] ;
47 static char log_buffer
[LOG_BUFFER_SIZE
] ;
50 main (int argc
, char *argv
[])
55 { printf ("Usage : %s <test>\n", argv
[0]) ;
56 printf (" Where <test> is one of the following:\n") ;
57 printf (" aiff - test AIFF file PEAK chunk\n") ;
58 printf (" caf - test CAF file PEAK chunk\n") ;
59 printf (" wav - test WAV file peak chunk\n") ;
60 printf (" all - perform all tests\n") ;
64 do_all
= ! strcmp (argv
[1], "all") ;
66 if (do_all
|| ! strcmp (argv
[1], "wav"))
67 { test_float_peak ("peak_float.wav", SF_FORMAT_WAV
| SF_FORMAT_FLOAT
) ;
68 test_float_peak ("peak_float.wavex", SF_FORMAT_WAVEX
| SF_FORMAT_FLOAT
) ;
69 test_float_peak ("peak_float.rifx", SF_ENDIAN_BIG
| SF_FORMAT_WAV
| SF_FORMAT_FLOAT
) ;
71 read_write_peak_test ("rw_peak.wav", SF_FORMAT_WAV
| SF_FORMAT_FLOAT
) ;
72 read_write_peak_test ("rw_peak.wavex", SF_FORMAT_WAVEX
| SF_FORMAT_FLOAT
) ;
76 if (do_all
|| ! strcmp (argv
[1], "aiff"))
77 { test_float_peak ("peak_float.aiff", SF_FORMAT_AIFF
| SF_FORMAT_FLOAT
) ;
79 read_write_peak_test ("rw_peak.aiff", SF_FORMAT_AIFF
| SF_FORMAT_FLOAT
) ;
83 if (do_all
|| ! strcmp (argv
[1], "caf"))
84 { test_float_peak ("peak_float.caf", SF_FORMAT_CAF
| SF_FORMAT_FLOAT
) ;
86 read_write_peak_test ("rw_peak.caf", SF_FORMAT_CAF
| SF_FORMAT_FLOAT
) ;
91 { printf ("Mono : ************************************\n") ;
92 printf ("Mono : * No '%s' test defined.\n", argv
[1]) ;
93 printf ("Mono : ************************************\n") ;
100 /*============================================================================================
101 ** Here are the test functions.
105 test_float_peak (const char *filename
, int filetype
)
108 int k
, frames
, count
;
110 print_test_name ("test_float_peak", filename
) ;
112 memset (&sfinfo
, 0, sizeof (sfinfo
)) ;
113 sfinfo
.samplerate
= 44100 ;
114 sfinfo
.format
= filetype
;
115 sfinfo
.channels
= 4 ;
118 frames
= BUFFER_LEN
/ sfinfo
.channels
;
120 /* Create some random data with a peak value of 0.66. */
121 for (k
= 0 ; k
< BUFFER_LEN
; k
++)
122 data
[k
] = (rand () % 2000) / 3000.0 ;
124 /* Insert some larger peaks a know locations. */
125 data
[4 * (frames
/ 8) + 0] = (frames
/ 8) * 0.01 ; /* First channel */
126 data
[4 * (frames
/ 6) + 1] = (frames
/ 6) * 0.01 ; /* Second channel */
127 data
[4 * (frames
/ 4) + 2] = (frames
/ 4) * 0.01 ; /* Third channel */
128 data
[4 * (frames
/ 2) + 3] = (frames
/ 2) * 0.01 ; /* Fourth channel */
130 /* Write a file with PEAK chunks. */
131 file
= test_open_file_or_die (filename
, SFM_WRITE
, &sfinfo
, 0, __LINE__
) ;
133 /* Try to confuse the header writer by adding a removing the PEAK chunk. */
134 sf_command (file
, SFC_SET_ADD_PEAK_CHUNK
, NULL
, SF_TRUE
) ;
135 sf_command (file
, SFC_SET_ADD_PEAK_CHUNK
, NULL
, SF_FALSE
) ;
136 sf_command (file
, SFC_SET_ADD_PEAK_CHUNK
, NULL
, SF_TRUE
) ;
138 /* Write the data in four passed. The data is designed so that peaks will
139 ** be written in the different calls to sf_write_double ().
141 for (count
= 0 ; count
< 4 ; count
++)
142 test_write_double_or_die (file
, 0, data
+ count
* BUFFER_LEN
/ 4, BUFFER_LEN
/ 4, BUFFER_LEN
/ 4) ;
146 file
= test_open_file_or_die (filename
, SFM_READ
, &sfinfo
, 0, __LINE__
) ;
148 if (sfinfo
.format
!= filetype
)
149 { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n", __LINE__
, filetype
, sfinfo
.format
) ;
153 if (sfinfo
.frames
!= frames
)
154 { printf ("\n\nLine %d: Incorrect number of frames in file. (%d => %ld)\n", __LINE__
, frames
, (long) sfinfo
.frames
) ;
158 if (sfinfo
.channels
!= 4)
159 { printf ("\n\nLine %d: Incorrect number of channels in file.\n", __LINE__
) ;
163 /* Check these two commands. */
164 if (sf_command (file
, SFC_GET_SIGNAL_MAX
, data
, sizeof (double)) == SF_FALSE
)
165 { printf ("\n\nLine %d: Command should have returned SF_TRUE.\n", __LINE__
) ;
169 if (fabs (data
[0] - (frames
/ 2) * 0.01) > 0.01)
170 { 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) ;
174 if (sf_command (file
, SFC_GET_MAX_ALL_CHANNELS
, data
, sizeof (double) * sfinfo
.channels
) == SF_FALSE
)
175 { printf ("\n\nLine %d: Command should have returned SF_TRUE.\n", __LINE__
) ;
179 if (fabs (data
[3] - (frames
/ 2) * 0.01) > 0.01)
180 { 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) ;
184 /* Get the log buffer data. */
186 sf_command (file
, SFC_GET_LOG_INFO
, log_buffer
, LOG_BUFFER_SIZE
) ;
188 if (strlen (log_buffer
) == 0)
189 { printf ("\n\nLine %d: Empty log buffer,\n", __LINE__
) ;
193 check_logged_peaks (log_buffer
) ;
197 /* Write a file ***without*** PEAK chunks. */
198 file
= test_open_file_or_die (filename
, SFM_WRITE
, &sfinfo
, 0, __LINE__
) ;
200 /* Try to confuse the header writer by adding a removing the PEAK chunk. */
201 sf_command (file
, SFC_SET_ADD_PEAK_CHUNK
, NULL
, SF_FALSE
) ;
202 sf_command (file
, SFC_SET_ADD_PEAK_CHUNK
, NULL
, SF_TRUE
) ;
203 sf_command (file
, SFC_SET_ADD_PEAK_CHUNK
, NULL
, SF_FALSE
) ;
205 /* Write the data in four passed. The data is designed so that peaks will
206 ** be written in the different calls to sf_write_double ().
208 for (count
= 0 ; count
< 4 ; count
++)
209 test_write_double_or_die (file
, 0, data
+ count
* BUFFER_LEN
/ 4, BUFFER_LEN
/ 4, BUFFER_LEN
/ 4) ;
213 file
= test_open_file_or_die (filename
, SFM_READ
, &sfinfo
, 0, __LINE__
) ;
215 /* Check these two commands. */
216 if (sf_command (file
, SFC_GET_SIGNAL_MAX
, data
, sizeof (double)))
217 { printf ("\n\nLine %d: Command should have returned SF_FALSE.\n", __LINE__
) ;
221 if (sf_command (file
, SFC_GET_MAX_ALL_CHANNELS
, data
, sizeof (double) * sfinfo
.channels
))
222 { printf ("\n\nLine %d: Command should have returned SF_FALSE.\n", __LINE__
) ;
226 /* Get the log buffer data. */
228 sf_command (file
, SFC_GET_LOG_INFO
, log_buffer
, LOG_BUFFER_SIZE
) ;
230 if (strlen (log_buffer
) == 0)
231 { printf ("\n\nLine %d: Empty log buffer,\n", __LINE__
) ;
235 if (strstr (log_buffer
, "PEAK :") != NULL
)
236 { printf ("\n\nLine %d: Should not have a PEAK chunk in this file.\n\n", __LINE__
) ;
245 } /* test_float_peak */
248 check_logged_peaks (char *buffer
)
250 int k
, chan
, channel_count
, position
;
253 if (strstr (buffer
, "should") || strstr (buffer
, "*"))
254 { printf ("\n\nLine %d: Something wrong in buffer. Dumping.\n", __LINE__
) ;
260 cptr
= strstr (buffer
, "Channels") ;
261 if (cptr
&& sscanf (cptr
, "Channels : %d", &k
) == 1)
263 else if (cptr
&& sscanf (cptr
, "Channels / frame : %d", &k
) == 1)
266 { printf ("\n\nLine %d: Couldn't find channel count.\n", __LINE__
) ;
270 if (channel_count
!= 4)
271 { printf ("\n\nLine %d: Wrong channel count (4 ->%d).\n", __LINE__
, channel_count
) ;
275 if (! (cptr
= strstr (buffer
, "Ch Position Value")))
276 { printf ("\n\nLine %d: Can't find PEAK data.\n", __LINE__
) ;
280 for (k
= 0 ; k
< channel_count
; k
++)
281 { if (! (cptr
= strchr (cptr
, '\n')))
282 { printf ("\n\nLine %d: Got lost.\n", __LINE__
) ;
285 if (sscanf (cptr
, "%d %d %f", &chan
, &position
, &value
) != 3)
286 { printf ("\n\nLine %d: sscanf failed.\n", __LINE__
) ;
290 { printf ("\n\nLine %d: peak position for channel %d should not be at offset 0.\n", __LINE__
, chan
) ;
291 printf ("%s", buffer
) ;
294 if (chan
!= k
|| fabs ((position
) * 0.01 - value
) > 1e-6)
295 { printf ("\n\nLine %d: Error : peak value incorrect!\n", __LINE__
) ;
296 printf ("%s", buffer
) ;
297 printf ("\n\nLine %d: %d %f %f\n", __LINE__
, chan
, position
* 0.01, value
) ;
300 cptr
++ ; /* Move past current newline. */
303 } /* check_logged_peaks */
306 read_write_peak_test (const char *filename
, int filetype
)
310 double small_data
[10] ;
311 double max_peak
= 0.0 ;
314 print_test_name (__func__
, filename
) ;
316 for (k
= 0 ; k
< ARRAY_LEN (small_data
) ; k
++)
317 small_data
[k
] = 0.1 ;
319 sfinfo
.samplerate
= 44100 ;
320 sfinfo
.channels
= 2 ;
321 sfinfo
.format
= filetype
;
324 /* Open the file, add peak chunk and write samples with value 0.1. */
325 file
= test_open_file_or_die (filename
, SFM_WRITE
, &sfinfo
, SF_FALSE
, __LINE__
) ;
327 sf_command (file
, SFC_SET_ADD_PEAK_CHUNK
, NULL
, SF_TRUE
) ;
329 test_write_double_or_die (file
, 0, small_data
, ARRAY_LEN (small_data
), __LINE__
) ;
333 /* Open the fiel RDWR, write sample valied 1.25. */
334 file
= test_open_file_or_die (filename
, SFM_RDWR
, &sfinfo
, SF_FALSE
, __LINE__
) ;
336 for (k
= 0 ; k
< ARRAY_LEN (small_data
) ; k
++)
337 small_data
[k
] = 1.0 ;
339 test_write_double_or_die (file
, 0, small_data
, ARRAY_LEN (small_data
), __LINE__
) ;
341 sf_command (file
, SFC_GET_SIGNAL_MAX
, &max_peak
, sizeof (max_peak
)) ;
345 exit_if_true (max_peak
< 0.1, "\n\nLine %d : max peak (%5.3f) should not be 0.1.\n\n", __LINE__
, max_peak
) ;
347 /* Open the file and test the values written to the PEAK chunk. */
348 file
= test_open_file_or_die (filename
, SFM_READ
, &sfinfo
, SF_FALSE
, __LINE__
) ;
350 exit_if_true (sfinfo
.channels
* sfinfo
.frames
!= 2 * ARRAY_LEN (small_data
),
351 "Line %d : frame count is %ld, should be %d\n", __LINE__
, SF_COUNT_TO_LONG (sfinfo
.frames
), 2 * ARRAY_LEN (small_data
)) ;
353 sf_command (file
, SFC_GET_SIGNAL_MAX
, &max_peak
, sizeof (double)) ;
357 exit_if_true (max_peak
< 1.0, "\n\nLine %d : max peak (%5.3f) should be 1.0.\n\n", __LINE__
, max_peak
) ;
361 } /* read_write_peak_test */