annotate src/libsndfile-1.0.27/src/double64.c @ 65:a69c1527268d

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