1[+ AutoGen5 template c +] 2/* 3** Copyright (C) 1999-2012 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 <math.h> 26#include <inttypes.h> 27 28#if HAVE_UNISTD_H 29#include <unistd.h> 30#else 31#include "sf_unistd.h" 32#endif 33 34#include <sndfile.h> 35 36#include "utils.h" 37 38#ifndef M_PI 39#define M_PI 3.14159265358979323846264338 40#endif 41 42#define HALF_BUFFER_SIZE (1 << 12) 43#define BUFFER_SIZE (2 * HALF_BUFFER_SIZE) 44 45#define SINE_AMP 1.1 46#define MAX_ERROR 0.0202 47 48[+ FOR float_type +] 49[+ FOR data_type 50+]static void [+ (get "float_short_name") +]_scale_clip_test_[+ (get "name") +] (const char *filename, int filetype, float maxval) ; 51[+ ENDFOR data_type 52+][+ ENDFOR float_type +] 53 54[+ FOR float_type +] 55[+ FOR int_type 56+]static void [+ (get "float_short_name") +]_[+ (get "int_type_name") +]_clip_read_test (const char *filename, int filetype) ; 57[+ ENDFOR int_type 58+][+ ENDFOR float_type +] 59 60[+ FOR int_type +] 61[+ FOR float_type 62+]static void [+ (get "int_type_name") +]_[+ (get "float_short_name") +]_scale_write_test (const char *filename, int filetype) ; 63[+ ENDFOR float_type 64+][+ ENDFOR int_type +] 65 66typedef union 67{ double dbl [BUFFER_SIZE] ; 68 float flt [BUFFER_SIZE] ; 69 int i [BUFFER_SIZE] ; 70 short s [BUFFER_SIZE] ; 71} BUFFER ; 72 73/* Data buffer. */ 74static BUFFER buffer_out ; 75static BUFFER buffer_in ; 76 77int 78main (void) 79{ 80 flt_scale_clip_test_08 ("scale_clip_s8.au", SF_FORMAT_AU | SF_FORMAT_PCM_S8, 1.0 * 0x80) ; 81 flt_scale_clip_test_08 ("scale_clip_u8.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_U8, 1.0 * 0x80) ; 82 83 dbl_scale_clip_test_08 ("scale_clip_s8.au", SF_FORMAT_AU | SF_FORMAT_PCM_S8, 1.0 * 0x80) ; 84 dbl_scale_clip_test_08 ("scale_clip_u8.wav", SF_FORMAT_WAV | SF_FORMAT_PCM_U8, 1.0 * 0x80) ; 85 86 /* 87 ** Now use SF_FORMAT_AU where possible because it allows both 88 ** big and little endian files. 89 */ 90 91 flt_scale_clip_test_16 ("scale_clip_be16.au", SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_PCM_16, 1.0 * 0x8000) ; 92 flt_scale_clip_test_16 ("scale_clip_le16.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_PCM_16, 1.0 * 0x8000) ; 93 flt_scale_clip_test_24 ("scale_clip_be24.au", SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_PCM_24, 1.0 * 0x800000) ; 94 flt_scale_clip_test_24 ("scale_clip_le24.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_PCM_24, 1.0 * 0x800000) ; 95 flt_scale_clip_test_32 ("scale_clip_be32.au", SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_PCM_32, 1.0 * 0x80000000) ; 96 flt_scale_clip_test_32 ("scale_clip_le32.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_PCM_32, 1.0 * 0x80000000) ; 97 98 dbl_scale_clip_test_16 ("scale_clip_be16.au", SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_PCM_16, 1.0 * 0x8000) ; 99 dbl_scale_clip_test_16 ("scale_clip_le16.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_PCM_16, 1.0 * 0x8000) ; 100 dbl_scale_clip_test_24 ("scale_clip_be24.au", SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_PCM_24, 1.0 * 0x800000) ; 101 dbl_scale_clip_test_24 ("scale_clip_le24.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_PCM_24, 1.0 * 0x800000) ; 102 dbl_scale_clip_test_32 ("scale_clip_be32.au", SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_PCM_32, 1.0 * 0x80000000) ; 103 dbl_scale_clip_test_32 ("scale_clip_le32.au", SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_PCM_32, 1.0 * 0x80000000) ; 104 105 flt_short_clip_read_test ("flt_short.au" , SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_FLOAT) ; 106 flt_int_clip_read_test ("flt_int.au" , SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_FLOAT) ; 107 dbl_short_clip_read_test ("dbl_short.au" , SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_DOUBLE) ; 108 dbl_int_clip_read_test ("dbl_int.au" , SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_DOUBLE) ; 109 110 short_flt_scale_write_test ("short_flt.au" , SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_FLOAT) ; 111 int_flt_scale_write_test ("int_flt.au" , SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_FLOAT) ; 112 short_dbl_scale_write_test ("short_dbl.au" , SF_ENDIAN_BIG | SF_FORMAT_AU | SF_FORMAT_DOUBLE) ; 113 int_dbl_scale_write_test ("int_dbl.au" , SF_ENDIAN_LITTLE | SF_FORMAT_AU | SF_FORMAT_DOUBLE) ; 114 115 return 0 ; 116} /* main */ 117 118/*============================================================================================ 119** Here are the test functions. 120*/ 121 122[+ FOR float_type +] 123[+ FOR data_type 124+]static void 125[+ (get "float_short_name") +]_scale_clip_test_[+ (get "name") +] (const char *filename, int filetype, float maxval) 126{ SNDFILE *file ; 127 SF_INFO sfinfo ; 128 int k ; 129 [+ (get "float_type_name") +] *data_out, *data_in ; 130 double diff, clip_max_diff ; 131 132 print_test_name ("[+ (get "float_short_name") +]_scale_clip_test_[+ (get "name") +]", filename) ; 133 134 data_out = buffer_out.[+ (get "float_short_name") +] ; 135 data_in = buffer_in.[+ (get "float_short_name") +] ; 136 137 for (k = 0 ; k < HALF_BUFFER_SIZE ; k++) 138 { data_out [k] = 1.2 * sin (2 * M_PI * k / HALF_BUFFER_SIZE) ; 139 data_out [k + HALF_BUFFER_SIZE] = data_out [k] * maxval ; 140 } ; 141 142 sfinfo.samplerate = 44100 ; 143 sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */ 144 sfinfo.channels = 1 ; 145 sfinfo.format = filetype ; 146 147 /* 148 ** Write two versions of the data: 149 ** normalized and clipped 150 ** un-normalized and clipped. 151 */ 152 153 file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ; 154 sf_command (file, SFC_SET_CLIPPING, NULL, SF_TRUE) ; 155 test_write_[+ (get "float_type_name") +]_or_die (file, 0, data_out, HALF_BUFFER_SIZE, __LINE__) ; 156 sf_command (file, SFC_SET_NORM_[+ (get "float_upper_name") +], NULL, SF_FALSE) ; 157 test_write_[+ (get "float_type_name") +]_or_die (file, 0, data_out + HALF_BUFFER_SIZE, HALF_BUFFER_SIZE, __LINE__) ; 158 sf_close (file) ; 159 160 memset (&buffer_in, 0, sizeof (buffer_in)) ; 161 162 file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ; 163 164 sfinfo.format &= (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK) ; 165 166 if (sfinfo.format != (filetype & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK))) 167 { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n\n", __LINE__, filetype, sfinfo.format) ; 168 exit (1) ; 169 } ; 170 171 if (sfinfo.frames != BUFFER_SIZE) 172 { printf ("\n\nLine %d: Incorrect number of frames in file (%d => %" PRId64 ").\n\n", __LINE__, BUFFER_SIZE, sfinfo.frames) ; 173 exit (1) ; 174 } ; 175 176 if (sfinfo.channels != 1) 177 { printf ("\n\nLine %d: Incorrect number of channels in file.\n\n", __LINE__) ; 178 exit (1) ; 179 } ; 180 181 check_log_buffer_or_die (file, __LINE__) ; 182 183 test_read_[+ (get "float_type_name") +]_or_die (file, 0, data_in, HALF_BUFFER_SIZE, __LINE__) ; 184 sf_command (file, SFC_SET_NORM_[+ (get "float_upper_name") +], NULL, SF_FALSE) ; 185 test_read_[+ (get "float_type_name") +]_or_die (file, 0, data_in + HALF_BUFFER_SIZE, HALF_BUFFER_SIZE, __LINE__) ; 186 sf_close (file) ; 187 188 /* Check normalized version. */ 189 clip_max_diff = 0.0 ; 190 for (k = 0 ; k < HALF_BUFFER_SIZE ; k++) 191 { if (fabs (data_in [k]) > 1.0) 192 { printf ("\n\nLine %d: Input sample %d/%d (%f) has not been clipped.\n\n", __LINE__, k, BUFFER_SIZE, data_in [k]) ; 193 exit (1) ; 194 } ; 195 196 if (data_out [k] * data_in [k] < 0.0) 197 { printf ("\n\nLine %d: Data wrap around at index %d/%d.\n\n", __LINE__, k, BUFFER_SIZE) ; 198 exit (1) ; 199 } ; 200 201 if (fabs (data_out [k]) > 1.0) 202 continue ; 203 204 diff = fabs (data_out [k] - data_in [k]) ; 205 if (diff > clip_max_diff) 206 clip_max_diff = diff ; 207 } ; 208 209 if (clip_max_diff < 1e-20) 210 { printf ("\n\nLine %d: Clipping difference (%e) too small (normalized).\n\n", __LINE__, clip_max_diff) ; 211 exit (1) ; 212 } ; 213 214 if (clip_max_diff > [+ (get "error_val") +]) 215 { printf ("\n\nLine %d: Clipping difference (%e) too large (normalized).\n\n", __LINE__, clip_max_diff) ; 216 exit (1) ; 217 } ; 218 219 /* Check the un-normalized data. */ 220 clip_max_diff = 0.0 ; 221 for (k = HALF_BUFFER_SIZE ; k < BUFFER_SIZE ; k++) 222 { if (fabs (data_in [k]) > maxval) 223 { printf ("\n\nLine %d: Input sample %d/%d (%f) has not been clipped.\n\n", __LINE__, k, BUFFER_SIZE, data_in [k]) ; 224 exit (1) ; 225 } ; 226 227 if (data_out [k] * data_in [k] < 0.0) 228 { printf ("\n\nLine %d: Data wrap around at index %d/%d.\n\n", __LINE__, k, BUFFER_SIZE) ; 229 exit (1) ; 230 } ; 231 232 if (fabs (data_out [k]) > maxval) 233 continue ; 234 235 diff = fabs (data_out [k] - data_in [k]) ; 236 if (diff > clip_max_diff) 237 clip_max_diff = diff ; 238 } ; 239 240 if (clip_max_diff < 1e-20) 241 { printf ("\n\nLine %d: Clipping difference (%e) too small (un-normalized).\n\n", __LINE__, clip_max_diff) ; 242 exit (1) ; 243 } ; 244 245 if (clip_max_diff > 1.0) 246 { printf ("\n\nLine %d: Clipping difference (%e) too large (un-normalised).\n\n", __LINE__, clip_max_diff) ; 247 exit (1) ; 248 } ; 249 250 printf ("ok\n") ; 251 unlink (filename) ; 252} /* [+ (get "float_short_name") +]_scale_clip_test_[+ (get "name") +] */ 253 254[+ ENDFOR data_type 255+] 256[+ ENDFOR float_type +] 257 258/*============================================================================== 259*/ 260 261[+ FOR float_type +] 262[+ FOR int_type 263+]static void [+ (get "float_short_name") +]_[+ (get "int_type_name") +]_clip_read_test (const char *filename, int filetype) 264{ SNDFILE *file ; 265 SF_INFO sfinfo ; 266 [+ (get "float_type_name") +] *data_out ; 267 [+ (get "int_type_name") +] *data_in, max_value ; 268 int k ; 269 270 print_test_name ("[+ (get "float_short_name") +]_[+ (get "int_type_name") +]_clip_read_test", filename) ; 271 272 data_out = buffer_out.[+ (get "float_short_name") +] ; 273 data_in = buffer_in.[+ (get "int_short_name") +] ; 274 275 for (k = 0 ; k < BUFFER_SIZE ; k++) 276 data_out [k] = 0.995 * sin (4 * M_PI * k / BUFFER_SIZE) ; 277 data_out [BUFFER_SIZE / 8] = 1.0 ; 278 data_out [3 * BUFFER_SIZE / 8] = -1.000000001 ; 279 data_out [5 * BUFFER_SIZE / 8] = 1.0 ; 280 data_out [7 * BUFFER_SIZE / 8] = -1.000000001 ; 281 282 memset (&sfinfo, 0, sizeof (sfinfo)) ; 283 sfinfo.samplerate = 44100 ; 284 sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */ 285 sfinfo.channels = 1 ; 286 sfinfo.format = filetype ; 287 288 /* Save unclipped data to the file. */ 289 file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ; 290 test_write_[+ (get "float_type_name") +]_or_die (file, 0, data_out, BUFFER_SIZE, __LINE__) ; 291 sf_close (file) ; 292 293 memset (&sfinfo, 0, sizeof (sfinfo)) ; 294 295 file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ; 296 sf_command (file, SFC_SET_SCALE_FLOAT_INT_READ, NULL, SF_TRUE) ; 297 298 sfinfo.format &= (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK) ; 299 300 if (sfinfo.format != (filetype & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK))) 301 { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n\n", __LINE__, filetype, sfinfo.format) ; 302 exit (1) ; 303 } ; 304 305 if (sfinfo.frames != BUFFER_SIZE) 306 { printf ("\n\nLine %d: Incorrect number of frames in file (%d => %" PRId64 ").\n\n", __LINE__, BUFFER_SIZE, sfinfo.frames) ; 307 exit (1) ; 308 } ; 309 310 if (sfinfo.channels != 1) 311 { printf ("\n\nLine %d: Incorrect number of channels in file.\n\n", __LINE__) ; 312 exit (1) ; 313 } ; 314 315 check_log_buffer_or_die (file, __LINE__) ; 316 317 sf_command (file, SFC_SET_CLIPPING, NULL, SF_TRUE) ; 318 test_read_[+ (get "int_type_name") +]_or_die (file, 0, data_in, BUFFER_SIZE, __LINE__) ; 319 /*-sf_command (file, SFC_SET_NORM_[+ (get "float_upper_name") +], NULL, SF_FALSE) ;-*/ 320 sf_close (file) ; 321 322 /* Check the first half. */ 323 max_value = 0 ; 324 for (k = 0 ; k < sfinfo.frames ; k++) 325 { /* Check if data_out has different sign from data_in. */ 326 if ((data_out [k] < 0.0 && data_in [k] > 0) || (data_out [k] > 0.0 && data_in [k] < 0)) 327 { printf ("\n\nLine %d: Data wrap around at index %d/%d (%f -> %d).\n\n", __LINE__, k, BUFFER_SIZE, data_out [k], data_in [k]) ; 328 exit (1) ; 329 } ; 330 max_value = (max_value > abs (data_in [k])) ? max_value : abs (data_in [k]) ; 331 } ; 332 333 unlink (filename) ; 334 puts ("ok") ; 335} /* [+ (get "float_short_name") +]_[+ (get "int_type_name") +]_clip_read_test */ 336[+ ENDFOR int_type 337+][+ ENDFOR float_type +] 338 339/*============================================================================== 340*/ 341 342[+ FOR int_type +] 343[+ FOR float_type 344+]static void [+ (get "int_type_name") +]_[+ (get "float_short_name") +]_scale_write_test (const char *filename, int filetype) 345{ SNDFILE *file ; 346 SF_INFO sfinfo ; 347 [+ (get "int_type_name") +] *data_out ; 348 [+ (get "float_type_name") +] *data_in, max_value ; 349 int k ; 350 351 print_test_name ("[+ (get "int_type_name") +]_[+ (get "float_short_name") +]_clip_write_test", filename) ; 352 353 data_out = buffer_out.[+ (get "int_short_name") +] ; 354 data_in = buffer_in.[+ (get "float_short_name") +] ; 355 356 for (k = 0 ; k < BUFFER_SIZE ; k++) 357 data_out [k] = [+ (get "float_to_int") +] ([+ (get "int_max_value") +] * 0.995 * sin (4 * M_PI * k / BUFFER_SIZE)) ; 358 359 memset (&sfinfo, 0, sizeof (sfinfo)) ; 360 sfinfo.samplerate = 44100 ; 361 sfinfo.frames = 123456789 ; /* Wrong length. Library should correct this on sf_close. */ 362 sfinfo.channels = 1 ; 363 sfinfo.format = filetype ; 364 365 file = test_open_file_or_die (filename, SFM_WRITE, &sfinfo, SF_TRUE, __LINE__) ; 366 test_write_[+ (get "int_type_name") +]_or_die (file, 0, data_out, BUFFER_SIZE, __LINE__) ; 367 sf_command (file, SFC_SET_SCALE_INT_FLOAT_WRITE, NULL, SF_TRUE) ; 368 test_write_[+ (get "int_type_name") +]_or_die (file, 0, data_out, BUFFER_SIZE, __LINE__) ; 369 sf_command (file, SFC_SET_SCALE_INT_FLOAT_WRITE, NULL, SF_FALSE) ; 370 test_write_[+ (get "int_type_name") +]_or_die (file, 0, data_out, BUFFER_SIZE, __LINE__) ; 371 sf_close (file) ; 372 373 memset (&sfinfo, 0, sizeof (sfinfo)) ; 374 375 file = test_open_file_or_die (filename, SFM_READ, &sfinfo, SF_TRUE, __LINE__) ; 376 377 sfinfo.format &= (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK) ; 378 379 if (sfinfo.format != (filetype & (SF_FORMAT_TYPEMASK | SF_FORMAT_SUBMASK))) 380 { printf ("\n\nLine %d: Returned format incorrect (0x%08X => 0x%08X).\n\n", __LINE__, filetype, sfinfo.format) ; 381 exit (1) ; 382 } ; 383 384 if (sfinfo.frames != 3 * BUFFER_SIZE) 385 { printf ("\n\nLine %d: Incorrect number of frames in file (%d => %" PRId64 ").\n\n", __LINE__, 3 * BUFFER_SIZE, sfinfo.frames) ; 386 exit (1) ; 387 } ; 388 389 if (sfinfo.channels != 1) 390 { printf ("\n\nLine %d: Incorrect number of channels in file.\n\n", __LINE__) ; 391 exit (1) ; 392 } ; 393 394 check_log_buffer_or_die (file, __LINE__) ; 395 396 /* Check the first section. */ 397 test_read_[+ (get "float_type_name") +]_or_die (file, 0, data_in, BUFFER_SIZE, __LINE__) ; 398 399 max_value = 0.0 ; 400 for (k = 0 ; k < BUFFER_SIZE ; k++) 401 max_value = (max_value > fabs (data_in [k])) ? max_value : fabs (data_in [k]) ; 402 403 if (max_value < 1000.0) 404 { printf ("\n\nLine %d: Max value (%f) < 1000.0.\n\n", __LINE__, max_value) ; 405 exit (1) ; 406 } ; 407 408 /* Check the second section. */ 409 test_read_[+ (get "float_type_name") +]_or_die (file, 0, data_in, BUFFER_SIZE, __LINE__) ; 410 411 max_value = 0.0 ; 412 for (k = 0 ; k < BUFFER_SIZE ; k++) 413 max_value = (max_value > fabs (data_in [k])) ? max_value : fabs (data_in [k]) ; 414 415 if (max_value > 1.0) 416 { printf ("\n\nLine %d: Max value (%f) > 1.0.\n\n", __LINE__, max_value) ; 417 exit (1) ; 418 } ; 419 420 /* Check the third section. */ 421 test_read_[+ (get "float_type_name") +]_or_die (file, 0, data_in, BUFFER_SIZE, __LINE__) ; 422 423 max_value = 0.0 ; 424 for (k = 0 ; k < BUFFER_SIZE ; k++) 425 max_value = (max_value > fabs (data_in [k])) ? max_value : fabs (data_in [k]) ; 426 427 if (max_value < 1000.0) 428 { printf ("\n\nLine %d: Max value (%f) < 1000.0.\n\n", __LINE__, max_value) ; 429 exit (1) ; 430 } ; 431 432 sf_close (file) ; 433 434 unlink (filename) ; 435 puts ("ok") ; 436} /* [+ (get "int_type_name") +]_[+ (get "float_short_name") +]_scale_write_test */ 437[+ ENDFOR float_type 438+][+ ENDFOR int_type +] 439 440 441