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