1/* 2** Copyright (C) 1999-2015 Erik de Castro Lopo <erikd@mega-nerd.com> 3** 4** This program is free software; you can redistribute it and/or modify 5** it under the terms of the GNU Lesser General Public License as published by 6** the Free Software Foundation; either version 2.1 of the License, or 7** (at your option) any later version. 8** 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 Lesser General Public License for more details. 13** 14** You should have received a copy of the GNU Lesser 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. 17*/ 18 19#include "sfconfig.h" 20 21#include <stdio.h> 22#include <stdlib.h> 23#include <string.h> 24#include <limits.h> 25#include <math.h> 26 27#include "sndfile.h" 28#include "sfendian.h" 29#include "common.h" 30 31#if CPU_IS_LITTLE_ENDIAN 32 #define DOUBLE64_READ double64_le_read 33 #define DOUBLE64_WRITE double64_le_write 34#elif CPU_IS_BIG_ENDIAN 35 #define DOUBLE64_READ double64_be_read 36 #define DOUBLE64_WRITE double64_be_write 37#endif 38 39/* A 32 number which will not overflow when multiplied by sizeof (double). */ 40#define SENSIBLE_LEN (0x8000000) 41 42/*-------------------------------------------------------------------------------------------- 43** Processor floating point capabilities. double64_get_capability () returns one of the 44** latter three values. 45*/ 46 47enum 48{ DOUBLE_UNKNOWN = 0x00, 49 DOUBLE_CAN_RW_LE = 0x23, 50 DOUBLE_CAN_RW_BE = 0x34, 51 DOUBLE_BROKEN_LE = 0x45, 52 DOUBLE_BROKEN_BE = 0x56 53} ; 54 55/*-------------------------------------------------------------------------------------------- 56** Prototypes for private functions. 57*/ 58 59static sf_count_t host_read_d2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; 60static sf_count_t host_read_d2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; 61static sf_count_t host_read_d2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; 62static sf_count_t host_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; 63 64static sf_count_t host_write_s2d (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; 65static sf_count_t host_write_i2d (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; 66static sf_count_t host_write_f2d (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; 67static sf_count_t host_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; 68 69static void double64_peak_update (SF_PRIVATE *psf, const double *buffer, int count, sf_count_t indx) ; 70 71static int double64_get_capability (SF_PRIVATE *psf) ; 72 73static sf_count_t replace_read_d2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; 74static sf_count_t replace_read_d2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; 75static sf_count_t replace_read_d2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; 76static sf_count_t replace_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; 77 78static sf_count_t replace_write_s2d (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ; 79static sf_count_t replace_write_i2d (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ; 80static sf_count_t replace_write_f2d (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ; 81static sf_count_t replace_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ; 82 83static void d2bd_read (double *buffer, int count) ; 84static void bd2d_write (double *buffer, int count) ; 85 86/*-------------------------------------------------------------------------------------------- 87** Exported functions. 88*/ 89 90int 91double64_init (SF_PRIVATE *psf) 92{ static int double64_caps ; 93 94 if (psf->sf.channels < 1 || psf->sf.channels > SF_MAX_CHANNELS) 95 { psf_log_printf (psf, "double64_init : internal error : channels = %d\n", psf->sf.channels) ; 96 return SFE_INTERNAL ; 97 } ; 98 99 double64_caps = double64_get_capability (psf) ; 100 101 psf->blockwidth = sizeof (double) * psf->sf.channels ; 102 103 if (psf->file.mode == SFM_READ || psf->file.mode == SFM_RDWR) 104 { switch (psf->endian + double64_caps) 105 { case (SF_ENDIAN_BIG + DOUBLE_CAN_RW_BE) : 106 psf->data_endswap = SF_FALSE ; 107 psf->read_short = host_read_d2s ; 108 psf->read_int = host_read_d2i ; 109 psf->read_float = host_read_d2f ; 110 psf->read_double = host_read_d ; 111 break ; 112 113 case (SF_ENDIAN_LITTLE + DOUBLE_CAN_RW_LE) : 114 psf->data_endswap = SF_FALSE ; 115 psf->read_short = host_read_d2s ; 116 psf->read_int = host_read_d2i ; 117 psf->read_float = host_read_d2f ; 118 psf->read_double = host_read_d ; 119 break ; 120 121 case (SF_ENDIAN_BIG + DOUBLE_CAN_RW_LE) : 122 psf->data_endswap = SF_TRUE ; 123 psf->read_short = host_read_d2s ; 124 psf->read_int = host_read_d2i ; 125 psf->read_float = host_read_d2f ; 126 psf->read_double = host_read_d ; 127 break ; 128 129 case (SF_ENDIAN_LITTLE + DOUBLE_CAN_RW_BE) : 130 psf->data_endswap = SF_TRUE ; 131 psf->read_short = host_read_d2s ; 132 psf->read_int = host_read_d2i ; 133 psf->read_float = host_read_d2f ; 134 psf->read_double = host_read_d ; 135 break ; 136 137 /* When the CPU is not IEEE compatible. */ 138 case (SF_ENDIAN_BIG + DOUBLE_BROKEN_BE) : 139 psf->data_endswap = SF_FALSE ; 140 psf->read_short = replace_read_d2s ; 141 psf->read_int = replace_read_d2i ; 142 psf->read_float = replace_read_d2f ; 143 psf->read_double = replace_read_d ; 144 break ; 145 146 case (SF_ENDIAN_LITTLE + DOUBLE_BROKEN_LE) : 147 psf->data_endswap = SF_FALSE ; 148 psf->read_short = replace_read_d2s ; 149 psf->read_int = replace_read_d2i ; 150 psf->read_float = replace_read_d2f ; 151 psf->read_double = replace_read_d ; 152 break ; 153 154 case (SF_ENDIAN_BIG + DOUBLE_BROKEN_LE) : 155 psf->data_endswap = SF_TRUE ; 156 psf->read_short = replace_read_d2s ; 157 psf->read_int = replace_read_d2i ; 158 psf->read_float = replace_read_d2f ; 159 psf->read_double = replace_read_d ; 160 break ; 161 162 case (SF_ENDIAN_LITTLE + DOUBLE_BROKEN_BE) : 163 psf->data_endswap = SF_TRUE ; 164 psf->read_short = replace_read_d2s ; 165 psf->read_int = replace_read_d2i ; 166 psf->read_float = replace_read_d2f ; 167 psf->read_double = replace_read_d ; 168 break ; 169 170 default : break ; 171 } ; 172 } ; 173 174 if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR) 175 { switch (psf->endian + double64_caps) 176 { case (SF_ENDIAN_LITTLE + DOUBLE_CAN_RW_LE) : 177 psf->data_endswap = SF_FALSE ; 178 psf->write_short = host_write_s2d ; 179 psf->write_int = host_write_i2d ; 180 psf->write_float = host_write_f2d ; 181 psf->write_double = host_write_d ; 182 break ; 183 184 case (SF_ENDIAN_BIG + DOUBLE_CAN_RW_BE) : 185 psf->data_endswap = SF_FALSE ; 186 psf->write_short = host_write_s2d ; 187 psf->write_int = host_write_i2d ; 188 psf->write_float = host_write_f2d ; 189 psf->write_double = host_write_d ; 190 break ; 191 192 case (SF_ENDIAN_BIG + DOUBLE_CAN_RW_LE) : 193 psf->data_endswap = SF_TRUE ; 194 psf->write_short = host_write_s2d ; 195 psf->write_int = host_write_i2d ; 196 psf->write_float = host_write_f2d ; 197 psf->write_double = host_write_d ; 198 break ; 199 200 case (SF_ENDIAN_LITTLE + DOUBLE_CAN_RW_BE) : 201 psf->data_endswap = SF_TRUE ; 202 psf->write_short = host_write_s2d ; 203 psf->write_int = host_write_i2d ; 204 psf->write_float = host_write_f2d ; 205 psf->write_double = host_write_d ; 206 break ; 207 208 /* When the CPU is not IEEE compatible. */ 209 case (SF_ENDIAN_LITTLE + DOUBLE_BROKEN_LE) : 210 psf->data_endswap = SF_FALSE ; 211 psf->write_short = replace_write_s2d ; 212 psf->write_int = replace_write_i2d ; 213 psf->write_float = replace_write_f2d ; 214 psf->write_double = replace_write_d ; 215 break ; 216 217 case (SF_ENDIAN_BIG + DOUBLE_BROKEN_BE) : 218 psf->data_endswap = SF_FALSE ; 219 psf->write_short = replace_write_s2d ; 220 psf->write_int = replace_write_i2d ; 221 psf->write_float = replace_write_f2d ; 222 psf->write_double = replace_write_d ; 223 break ; 224 225 case (SF_ENDIAN_BIG + DOUBLE_BROKEN_LE) : 226 psf->data_endswap = SF_TRUE ; 227 psf->write_short = replace_write_s2d ; 228 psf->write_int = replace_write_i2d ; 229 psf->write_float = replace_write_f2d ; 230 psf->write_double = replace_write_d ; 231 break ; 232 233 case (SF_ENDIAN_LITTLE + DOUBLE_BROKEN_BE) : 234 psf->data_endswap = SF_TRUE ; 235 psf->write_short = replace_write_s2d ; 236 psf->write_int = replace_write_i2d ; 237 psf->write_float = replace_write_f2d ; 238 psf->write_double = replace_write_d ; 239 break ; 240 241 default : break ; 242 } ; 243 } ; 244 245 if (psf->filelength > psf->dataoffset) 246 { psf->datalength = (psf->dataend > 0) ? psf->dataend - psf->dataoffset : 247 psf->filelength - psf->dataoffset ; 248 } 249 else 250 psf->datalength = 0 ; 251 252 psf->sf.frames = psf->datalength / psf->blockwidth ; 253 254 return 0 ; 255} /* double64_init */ 256 257/*---------------------------------------------------------------------------- 258** From : http://www.hpcf.cam.ac.uk/fp_formats.html 259** 260** 64 bit double precision layout (big endian) 261** Sign bit 0 262** Exponent bits 1-11 263** Mantissa bits 12-63 264** Exponent Offset 1023 265** 266** double single 267** 268** +INF 7FF0000000000000 7F800000 269** -INF FFF0000000000000 FF800000 270** NaN 7FF0000000000001 7F800001 271** to to 272** 7FFFFFFFFFFFFFFF 7FFFFFFF 273** and and 274** FFF0000000000001 FF800001 275** to to 276** FFFFFFFFFFFFFFFF FFFFFFFF 277** +OVER 7FEFFFFFFFFFFFFF 7F7FFFFF 278** -OVER FFEFFFFFFFFFFFFF FF7FFFFF 279** +UNDER 0010000000000000 00800000 280** -UNDER 8010000000000000 80800000 281*/ 282 283double 284double64_be_read (const unsigned char *cptr) 285{ int exponent, negative, upper, lower ; 286 double dvalue ; 287 288 negative = (cptr [0] & 0x80) ? 1 : 0 ; 289 exponent = ((cptr [0] & 0x7F) << 4) | ((cptr [1] >> 4) & 0xF) ; 290 291 /* Might not have a 64 bit long, so load the mantissa into a double. */ 292 upper = (((cptr [1] & 0xF) << 24) | (cptr [2] << 16) | (cptr [3] << 8) | cptr [4]) ; 293 lower = (cptr [5] << 16) | (cptr [6] << 8) | cptr [7] ; 294 295 if (exponent == 0 && upper == 0 && lower == 0) 296 return 0.0 ; 297 298 dvalue = upper + lower / ((double) 0x1000000) ; 299 dvalue += 0x10000000 ; 300 301 exponent = exponent - 0x3FF ; 302 303 dvalue = dvalue / ((double) 0x10000000) ; 304 305 if (negative) 306 dvalue *= -1 ; 307 308 if (exponent > 0) 309 dvalue *= pow (2.0, exponent) ; 310 else if (exponent < 0) 311 dvalue /= pow (2.0, abs (exponent)) ; 312 313 return dvalue ; 314} /* double64_be_read */ 315 316double 317double64_le_read (const unsigned char *cptr) 318{ int exponent, negative, upper, lower ; 319 double dvalue ; 320 321 negative = (cptr [7] & 0x80) ? 1 : 0 ; 322 exponent = ((cptr [7] & 0x7F) << 4) | ((cptr [6] >> 4) & 0xF) ; 323 324 /* Might not have a 64 bit long, so load the mantissa into a double. */ 325 upper = ((cptr [6] & 0xF) << 24) | (cptr [5] << 16) | (cptr [4] << 8) | cptr [3] ; 326 lower = (cptr [2] << 16) | (cptr [1] << 8) | cptr [0] ; 327 328 if (exponent == 0 && upper == 0 && lower == 0) 329 return 0.0 ; 330 331 dvalue = upper + lower / ((double) 0x1000000) ; 332 dvalue += 0x10000000 ; 333 334 exponent = exponent - 0x3FF ; 335 336 dvalue = dvalue / ((double) 0x10000000) ; 337 338 if (negative) 339 dvalue *= -1 ; 340 341 if (exponent > 0) 342 dvalue *= pow (2.0, exponent) ; 343 else if (exponent < 0) 344 dvalue /= pow (2.0, abs (exponent)) ; 345 346 return dvalue ; 347} /* double64_le_read */ 348 349void 350double64_be_write (double in, unsigned char *out) 351{ int exponent, mantissa ; 352 353 memset (out, 0, sizeof (double)) ; 354 355 if (fabs (in) < 1e-30) 356 return ; 357 358 if (in < 0.0) 359 { in *= -1.0 ; 360 out [0] |= 0x80 ; 361 } ; 362 363 in = frexp (in, &exponent) ; 364 365 exponent += 1022 ; 366 367 out [0] |= (exponent >> 4) & 0x7F ; 368 out [1] |= (exponent << 4) & 0xF0 ; 369 370 in *= 0x20000000 ; 371 mantissa = psf_lrint (floor (in)) ; 372 373 out [1] |= (mantissa >> 24) & 0xF ; 374 out [2] = (mantissa >> 16) & 0xFF ; 375 out [3] = (mantissa >> 8) & 0xFF ; 376 out [4] = mantissa & 0xFF ; 377 378 in = fmod (in, 1.0) ; 379 in *= 0x1000000 ; 380 mantissa = psf_lrint (floor (in)) ; 381 382 out [5] = (mantissa >> 16) & 0xFF ; 383 out [6] = (mantissa >> 8) & 0xFF ; 384 out [7] = mantissa & 0xFF ; 385 386 return ; 387} /* double64_be_write */ 388 389void 390double64_le_write (double in, unsigned char *out) 391{ int exponent, mantissa ; 392 393 memset (out, 0, sizeof (double)) ; 394 395 if (fabs (in) < 1e-30) 396 return ; 397 398 if (in < 0.0) 399 { in *= -1.0 ; 400 out [7] |= 0x80 ; 401 } ; 402 403 in = frexp (in, &exponent) ; 404 405 exponent += 1022 ; 406 407 out [7] |= (exponent >> 4) & 0x7F ; 408 out [6] |= (exponent << 4) & 0xF0 ; 409 410 in *= 0x20000000 ; 411 mantissa = psf_lrint (floor (in)) ; 412 413 out [6] |= (mantissa >> 24) & 0xF ; 414 out [5] = (mantissa >> 16) & 0xFF ; 415 out [4] = (mantissa >> 8) & 0xFF ; 416 out [3] = mantissa & 0xFF ; 417 418 in = fmod (in, 1.0) ; 419 in *= 0x1000000 ; 420 mantissa = psf_lrint (floor (in)) ; 421 422 out [2] = (mantissa >> 16) & 0xFF ; 423 out [1] = (mantissa >> 8) & 0xFF ; 424 out [0] = mantissa & 0xFF ; 425 426 return ; 427} /* double64_le_write */ 428 429/*============================================================================================== 430** Private functions. 431*/ 432 433static void 434double64_peak_update (SF_PRIVATE *psf, const double *buffer, int count, sf_count_t indx) 435{ int chan ; 436 int k, position ; 437 float fmaxval ; 438 439 for (chan = 0 ; chan < psf->sf.channels ; chan++) 440 { fmaxval = fabs (buffer [chan]) ; 441 position = 0 ; 442 for (k = chan ; k < count ; k += psf->sf.channels) 443 if (fmaxval < fabs (buffer [k])) 444 { fmaxval = fabs (buffer [k]) ; 445 position = k ; 446 } ; 447 448 if (fmaxval > psf->peak_info->peaks [chan].value) 449 { psf->peak_info->peaks [chan].value = fmaxval ; 450 psf->peak_info->peaks [chan].position = psf->write_current + indx + (position / psf->sf.channels) ; 451 } ; 452 } ; 453 454 return ; 455} /* double64_peak_update */ 456 457static int 458double64_get_capability (SF_PRIVATE *psf) 459{ union 460 { double d ; 461 unsigned char c [8] ; 462 } data ; 463 464 data.d = 1.234567890123456789 ; /* Some abitrary value. */ 465 466 if (! psf->ieee_replace) 467 { /* If this test is true ints and floats are compatible and little endian. */ 468 if (data.c [0] == 0xfb && data.c [1] == 0x59 && data.c [2] == 0x8c && data.c [3] == 0x42 && 469 data.c [4] == 0xca && data.c [5] == 0xc0 && data.c [6] == 0xf3 && data.c [7] == 0x3f) 470 return DOUBLE_CAN_RW_LE ; 471 472 /* If this test is true ints and floats are compatible and big endian. */ 473 if (data.c [0] == 0x3f && data.c [1] == 0xf3 && data.c [2] == 0xc0 && data.c [3] == 0xca && 474 data.c [4] == 0x42 && data.c [5] == 0x8c && data.c [6] == 0x59 && data.c [7] == 0xfb) 475 return DOUBLE_CAN_RW_BE ; 476 } ; 477 478 /* Doubles are broken. Don't expect reading or writing to be fast. */ 479 psf_log_printf (psf, "Using IEEE replacement code for double.\n") ; 480 481 return (CPU_IS_LITTLE_ENDIAN) ? DOUBLE_BROKEN_LE : DOUBLE_BROKEN_BE ; 482} /* double64_get_capability */ 483 484/*======================================================================================= 485*/ 486 487static void 488d2s_array (const double *src, int count, short *dest, double scale) 489{ for (int i = 0 ; i < count ; i++) 490 { dest [i] = psf_lrint (scale * src [i]) ; 491 } ; 492} /* d2s_array */ 493 494static void 495d2s_clip_array (const double *src, int count, short *dest, double scale) 496{ for (int i = 0 ; i < count ; i++) 497 { double tmp = scale * src [i] ; 498 499 if (tmp > 32767.0) 500 dest [i] = SHRT_MAX ; 501 else if (tmp < -32768.0) 502 dest [i] = SHRT_MIN ; 503 else 504 dest [i] = psf_lrint (tmp) ; 505 } ; 506} /* d2s_clip_array */ 507 508static void 509d2i_array (const double *src, int count, int *dest, double scale) 510{ for (int i = 0 ; i < count ; i++) 511 { dest [i] = psf_lrint (scale * src [i]) ; 512 } ; 513} /* d2i_array */ 514 515static void 516d2i_clip_array (const double *src, int count, int *dest, double scale) 517{ for (int i = 0 ; i < count ; i++) 518 { float tmp = scale * src [i] ; 519 520 if (CPU_CLIPS_POSITIVE == 0 && tmp > (1.0 * INT_MAX)) 521 dest [i] = INT_MAX ; 522 else if (CPU_CLIPS_NEGATIVE == 0 && tmp < (-1.0 * INT_MAX)) 523 dest [i] = INT_MIN ; 524 else 525 dest [i] = psf_lrint (tmp) ; 526 } ; 527} /* d2i_clip_array */ 528 529static inline void 530d2f_array (const double *src, int count, float *dest) 531{ for (int i = 0 ; i < count ; i++) 532 { dest [i] = src [i] ; 533 } ; 534} /* d2f_array */ 535 536static inline void 537s2d_array (const short *src, double *dest, int count, double scale) 538{ for (int i = 0 ; i < count ; i++) 539 { dest [i] = scale * src [i] ; 540 } ; 541} /* s2d_array */ 542 543static inline void 544i2d_array (const int *src, double *dest, int count, double scale) 545{ for (int i = 0 ; i < count ; i++) 546 { dest [i] = scale * src [i] ; 547 } ; 548} /* i2d_array */ 549 550static inline void 551f2d_array (const float *src, double *dest, int count) 552{ for (int i = 0 ; i < count ; i++) 553 { dest [i] = src [i] ; 554 } ; 555} /* f2d_array */ 556 557/*---------------------------------------------------------------------------------------------- 558*/ 559 560static sf_count_t 561host_read_d2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) 562{ BUF_UNION ubuf ; 563 void (*convert) (const double *, int, short *, double) ; 564 int bufferlen, readcount ; 565 sf_count_t total = 0 ; 566 double scale ; 567 568 convert = (psf->add_clipping) ? d2s_clip_array : d2s_array ; 569 bufferlen = ARRAY_LEN (ubuf.dbuf) ; 570 scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFF / psf->float_max ; 571 572 while (len > 0) 573 { if (len < bufferlen) 574 bufferlen = (int) len ; 575 readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; 576 577 if (psf->data_endswap == SF_TRUE) 578 endswap_double_array (ubuf.dbuf, readcount) ; 579 580 convert (ubuf.dbuf, readcount, ptr + total, scale) ; 581 total += readcount ; 582 len -= readcount ; 583 if (readcount < bufferlen) 584 break ; 585 } ; 586 587 return total ; 588} /* host_read_d2s */ 589 590static sf_count_t 591host_read_d2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) 592{ BUF_UNION ubuf ; 593 void (*convert) (const double *, int, int *, double) ; 594 int bufferlen, readcount ; 595 sf_count_t total = 0 ; 596 double scale ; 597 598 convert = (psf->add_clipping) ? d2i_clip_array : d2i_array ; 599 bufferlen = ARRAY_LEN (ubuf.dbuf) ; 600 scale = (psf->float_int_mult == 0) ? 1.0 : 2147483648.0f / psf->float_max ; 601 602 while (len > 0) 603 { if (len < bufferlen) 604 bufferlen = (int) len ; 605 readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; 606 607 if (psf->data_endswap == SF_TRUE) 608 endswap_double_array (ubuf.dbuf, bufferlen) ; 609 610 convert (ubuf.dbuf, readcount, ptr + total, scale) ; 611 total += readcount ; 612 len -= readcount ; 613 if (readcount < bufferlen) 614 break ; 615 } ; 616 617 return total ; 618} /* host_read_d2i */ 619 620static sf_count_t 621host_read_d2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) 622{ BUF_UNION ubuf ; 623 int bufferlen, readcount ; 624 sf_count_t total = 0 ; 625 626 bufferlen = ARRAY_LEN (ubuf.dbuf) ; 627 628 while (len > 0) 629 { if (len < bufferlen) 630 bufferlen = (int) len ; 631 readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; 632 633 if (psf->data_endswap == SF_TRUE) 634 endswap_double_array (ubuf.dbuf, readcount) ; 635 636 d2f_array (ubuf.dbuf, readcount, ptr + total) ; 637 total += readcount ; 638 len -= readcount ; 639 if (readcount < bufferlen) 640 break ; 641 } ; 642 643 return total ; 644} /* host_read_d2f */ 645 646static sf_count_t 647host_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) 648{ int bufferlen ; 649 sf_count_t readcount, total = 0 ; 650 651 readcount = psf_fread (ptr, sizeof (double), len, psf) ; 652 653 if (psf->data_endswap != SF_TRUE) 654 return readcount ; 655 656 /* If the read length was sensible, endswap output in one go. */ 657 if (readcount < SENSIBLE_LEN) 658 { endswap_double_array (ptr, readcount) ; 659 return readcount ; 660 } ; 661 662 bufferlen = SENSIBLE_LEN ; 663 while (len > 0) 664 { if (len < bufferlen) 665 bufferlen = (int) len ; 666 667 endswap_double_array (ptr + total, bufferlen) ; 668 669 total += bufferlen ; 670 len -= bufferlen ; 671 } ; 672 673 return total ; 674} /* host_read_d */ 675 676static sf_count_t 677host_write_s2d (SF_PRIVATE *psf, const short *ptr, sf_count_t len) 678{ BUF_UNION ubuf ; 679 int bufferlen, writecount ; 680 sf_count_t total = 0 ; 681 double scale ; 682 683 scale = (psf->scale_int_float == 0) ? 1.0 : 1.0 / 0x8000 ; 684 bufferlen = ARRAY_LEN (ubuf.dbuf) ; 685 686 while (len > 0) 687 { if (len < bufferlen) 688 bufferlen = (int) len ; 689 690 s2d_array (ptr + total, ubuf.dbuf, bufferlen, scale) ; 691 692 if (psf->peak_info) 693 double64_peak_update (psf, ubuf.dbuf, bufferlen, total / psf->sf.channels) ; 694 695 if (psf->data_endswap == SF_TRUE) 696 endswap_double_array (ubuf.dbuf, bufferlen) ; 697 698 writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; 699 total += writecount ; 700 if (writecount < bufferlen) 701 break ; 702 len -= writecount ; 703 } ; 704 705 return total ; 706} /* host_write_s2d */ 707 708static sf_count_t 709host_write_i2d (SF_PRIVATE *psf, const int *ptr, sf_count_t len) 710{ BUF_UNION ubuf ; 711 int bufferlen, writecount ; 712 sf_count_t total = 0 ; 713 double scale ; 714 715 scale = (psf->scale_int_float == 0) ? 1.0 : 1.0 / (8.0 * 0x10000000) ; 716 bufferlen = ARRAY_LEN (ubuf.dbuf) ; 717 718 while (len > 0) 719 { if (len < bufferlen) 720 bufferlen = (int) len ; 721 i2d_array (ptr + total, ubuf.dbuf, bufferlen, scale) ; 722 723 if (psf->peak_info) 724 double64_peak_update (psf, ubuf.dbuf, bufferlen, total / psf->sf.channels) ; 725 726 if (psf->data_endswap == SF_TRUE) 727 endswap_double_array (ubuf.dbuf, bufferlen) ; 728 729 writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; 730 total += writecount ; 731 if (writecount < bufferlen) 732 break ; 733 len -= writecount ; 734 } ; 735 736 return total ; 737} /* host_write_i2d */ 738 739static sf_count_t 740host_write_f2d (SF_PRIVATE *psf, const float *ptr, sf_count_t len) 741{ BUF_UNION ubuf ; 742 int bufferlen, writecount ; 743 sf_count_t total = 0 ; 744 745 bufferlen = ARRAY_LEN (ubuf.dbuf) ; 746 747 while (len > 0) 748 { if (len < bufferlen) 749 bufferlen = (int) len ; 750 f2d_array (ptr + total, ubuf.dbuf, bufferlen) ; 751 752 if (psf->peak_info) 753 double64_peak_update (psf, ubuf.dbuf, bufferlen, total / psf->sf.channels) ; 754 755 if (psf->data_endswap == SF_TRUE) 756 endswap_double_array (ubuf.dbuf, bufferlen) ; 757 758 writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; 759 total += writecount ; 760 if (writecount < bufferlen) 761 break ; 762 len -= writecount ; 763 } ; 764 765 return total ; 766} /* host_write_f2d */ 767 768static sf_count_t 769host_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) 770{ BUF_UNION ubuf ; 771 int bufferlen, writecount ; 772 sf_count_t total = 0 ; 773 774 if (psf->peak_info) 775 double64_peak_update (psf, ptr, len, 0) ; 776 777 if (psf->data_endswap != SF_TRUE) 778 return psf_fwrite (ptr, sizeof (double), len, psf) ; 779 780 bufferlen = ARRAY_LEN (ubuf.dbuf) ; 781 782 while (len > 0) 783 { if (len < bufferlen) 784 bufferlen = (int) len ; 785 786 endswap_double_copy (ubuf.dbuf, ptr + total, bufferlen) ; 787 788 writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; 789 total += writecount ; 790 if (writecount < bufferlen) 791 break ; 792 len -= writecount ; 793 } ; 794 795 return total ; 796} /* host_write_d */ 797 798/*======================================================================================= 799*/ 800 801static sf_count_t 802replace_read_d2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) 803{ BUF_UNION ubuf ; 804 int bufferlen, readcount ; 805 sf_count_t total = 0 ; 806 double scale ; 807 808 bufferlen = ARRAY_LEN (ubuf.dbuf) ; 809 scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFF / psf->float_max ; 810 811 while (len > 0) 812 { if (len < bufferlen) 813 bufferlen = (int) len ; 814 readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; 815 816 if (psf->data_endswap == SF_TRUE) 817 endswap_double_array (ubuf.dbuf, bufferlen) ; 818 819 d2bd_read (ubuf.dbuf, bufferlen) ; 820 821 d2s_array (ubuf.dbuf, readcount, ptr + total, scale) ; 822 total += readcount ; 823 if (readcount < bufferlen) 824 break ; 825 len -= readcount ; 826 } ; 827 828 return total ; 829} /* replace_read_d2s */ 830 831static sf_count_t 832replace_read_d2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) 833{ BUF_UNION ubuf ; 834 int bufferlen, readcount ; 835 sf_count_t total = 0 ; 836 double scale ; 837 838 bufferlen = ARRAY_LEN (ubuf.dbuf) ; 839 scale = (psf->float_int_mult == 0) ? 1.0 : 2147483648.0f / psf->float_max ; 840 841 while (len > 0) 842 { if (len < bufferlen) 843 bufferlen = (int) len ; 844 readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; 845 846 if (psf->data_endswap == SF_TRUE) 847 endswap_double_array (ubuf.dbuf, bufferlen) ; 848 849 d2bd_read (ubuf.dbuf, bufferlen) ; 850 851 d2i_array (ubuf.dbuf, readcount, ptr + total, scale) ; 852 total += readcount ; 853 if (readcount < bufferlen) 854 break ; 855 len -= readcount ; 856 } ; 857 858 return total ; 859} /* replace_read_d2i */ 860 861static sf_count_t 862replace_read_d2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) 863{ BUF_UNION ubuf ; 864 int bufferlen, readcount ; 865 sf_count_t total = 0 ; 866 867 bufferlen = ARRAY_LEN (ubuf.dbuf) ; 868 869 while (len > 0) 870 { if (len < bufferlen) 871 bufferlen = (int) len ; 872 readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; 873 874 if (psf->data_endswap == SF_TRUE) 875 endswap_double_array (ubuf.dbuf, bufferlen) ; 876 877 d2bd_read (ubuf.dbuf, bufferlen) ; 878 879 memcpy (ptr + total, ubuf.dbuf, bufferlen * sizeof (double)) ; 880 881 total += readcount ; 882 if (readcount < bufferlen) 883 break ; 884 len -= readcount ; 885 } ; 886 887 return total ; 888} /* replace_read_d2f */ 889 890static sf_count_t 891replace_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) 892{ BUF_UNION ubuf ; 893 int bufferlen, readcount ; 894 sf_count_t total = 0 ; 895 896 /* FIXME : This is probably nowhere near optimal. */ 897 bufferlen = ARRAY_LEN (ubuf.dbuf) ; 898 899 while (len > 0) 900 { if (len < bufferlen) 901 bufferlen = (int) len ; 902 readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ; 903 904 if (psf->data_endswap == SF_TRUE) 905 endswap_double_array (ubuf.dbuf, readcount) ; 906 907 d2bd_read (ubuf.dbuf, readcount) ; 908 909 memcpy (ptr + total, ubuf.dbuf, readcount * sizeof (double)) ; 910 911 total += readcount ; 912 if (readcount < bufferlen) 913 break ; 914 len -= readcount ; 915 } ; 916 917 return total ; 918} /* replace_read_d */ 919 920static sf_count_t 921replace_write_s2d (SF_PRIVATE *psf, const short *ptr, sf_count_t len) 922{ BUF_UNION ubuf ; 923 int bufferlen, writecount ; 924 sf_count_t total = 0 ; 925 double scale ; 926 927 scale = (psf->scale_int_float == 0) ? 1.0 : 1.0 / 0x8000 ; 928 bufferlen = ARRAY_LEN (ubuf.dbuf) ; 929 930 while (len > 0) 931 { if (len < bufferlen) 932 bufferlen = (int) len ; 933 s2d_array (ptr + total, ubuf.dbuf, bufferlen, scale) ; 934 935 if (psf->peak_info) 936 double64_peak_update (psf, ubuf.dbuf, bufferlen, total / psf->sf.channels) ; 937 938 bd2d_write (ubuf.dbuf, bufferlen) ; 939 940 if (psf->data_endswap == SF_TRUE) 941 endswap_double_array (ubuf.dbuf, bufferlen) ; 942 943 writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; 944 total += writecount ; 945 if (writecount < bufferlen) 946 break ; 947 len -= writecount ; 948 } ; 949 950 return total ; 951} /* replace_write_s2d */ 952 953static sf_count_t 954replace_write_i2d (SF_PRIVATE *psf, const int *ptr, sf_count_t len) 955{ BUF_UNION ubuf ; 956 int bufferlen, writecount ; 957 sf_count_t total = 0 ; 958 double scale ; 959 960 scale = (psf->scale_int_float == 0) ? 1.0 : 1.0 / (8.0 * 0x10000000) ; 961 bufferlen = ARRAY_LEN (ubuf.dbuf) ; 962 963 while (len > 0) 964 { if (len < bufferlen) 965 bufferlen = (int) len ; 966 i2d_array (ptr + total, ubuf.dbuf, bufferlen, scale) ; 967 968 if (psf->peak_info) 969 double64_peak_update (psf, ubuf.dbuf, bufferlen, total / psf->sf.channels) ; 970 971 bd2d_write (ubuf.dbuf, bufferlen) ; 972 973 if (psf->data_endswap == SF_TRUE) 974 endswap_double_array (ubuf.dbuf, bufferlen) ; 975 976 writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; 977 total += writecount ; 978 if (writecount < bufferlen) 979 break ; 980 len -= writecount ; 981 } ; 982 983 return total ; 984} /* replace_write_i2d */ 985 986static sf_count_t 987replace_write_f2d (SF_PRIVATE *psf, const float *ptr, sf_count_t len) 988{ BUF_UNION ubuf ; 989 int bufferlen, writecount ; 990 sf_count_t total = 0 ; 991 992 bufferlen = ARRAY_LEN (ubuf.dbuf) ; 993 994 while (len > 0) 995 { if (len < bufferlen) 996 bufferlen = (int) len ; 997 f2d_array (ptr + total, ubuf.dbuf, bufferlen) ; 998 999 bd2d_write (ubuf.dbuf, bufferlen) ; 1000 1001 if (psf->data_endswap == SF_TRUE) 1002 endswap_double_array (ubuf.dbuf, bufferlen) ; 1003 1004 writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; 1005 total += writecount ; 1006 if (writecount < bufferlen) 1007 break ; 1008 len -= writecount ; 1009 } ; 1010 1011 return total ; 1012} /* replace_write_f2d */ 1013 1014static sf_count_t 1015replace_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) 1016{ BUF_UNION ubuf ; 1017 int bufferlen, writecount ; 1018 sf_count_t total = 0 ; 1019 1020 /* FIXME : This is probably nowhere near optimal. */ 1021 if (psf->peak_info) 1022 double64_peak_update (psf, ptr, len, 0) ; 1023 1024 bufferlen = ARRAY_LEN (ubuf.dbuf) ; 1025 1026 while (len > 0) 1027 { if (len < bufferlen) 1028 bufferlen = (int) len ; 1029 1030 memcpy (ubuf.dbuf, ptr + total, bufferlen * sizeof (double)) ; 1031 1032 bd2d_write (ubuf.dbuf, bufferlen) ; 1033 1034 if (psf->data_endswap == SF_TRUE) 1035 endswap_double_array (ubuf.dbuf, bufferlen) ; 1036 1037 writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ; 1038 total += writecount ; 1039 if (writecount < bufferlen) 1040 break ; 1041 len -= writecount ; 1042 } ; 1043 1044 return total ; 1045} /* replace_write_d */ 1046 1047/*---------------------------------------------------------------------------------------------- 1048*/ 1049 1050static void 1051d2bd_read (double *buffer, int count) 1052{ for (int i = 0 ; i < count ; i++) 1053 { buffer [i] = DOUBLE64_READ ((unsigned char *) &buffer [i]) ; 1054 } ; 1055} /* d2bd_read */ 1056 1057static void 1058bd2d_write (double *buffer, int count) 1059{ for (int i = 0 ; i < count ; i++) 1060 { DOUBLE64_WRITE (buffer [i], (unsigned char*) &buffer [i]) ; 1061 } ; 1062} /* bd2d_write */ 1063 1064