annotate src/libsndfile-1.0.27/tests/peak_chunk_test.c @ 83:ae30d91d2ffe

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