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
47 enum
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
59 static sf_count_t host_read_d2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
60 static sf_count_t host_read_d2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
61 static sf_count_t host_read_d2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
62 static sf_count_t host_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
63
64 static sf_count_t host_write_s2d (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
65 static sf_count_t host_write_i2d (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
66 static sf_count_t host_write_f2d (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
67 static sf_count_t host_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
68
69 static void double64_peak_update (SF_PRIVATE *psf, const double *buffer, int count, sf_count_t indx) ;
70
71 static int double64_get_capability (SF_PRIVATE *psf) ;
72
73 static sf_count_t replace_read_d2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
74 static sf_count_t replace_read_d2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
75 static sf_count_t replace_read_d2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
76 static sf_count_t replace_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
77
78 static sf_count_t replace_write_s2d (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
79 static sf_count_t replace_write_i2d (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
80 static sf_count_t replace_write_f2d (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
81 static sf_count_t replace_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
82
83 static void d2bd_read (double *buffer, int count) ;
84 static void bd2d_write (double *buffer, int count) ;
85
86 /*--------------------------------------------------------------------------------------------
87 ** Exported functions.
88 */
89
90 int
double64_init(SF_PRIVATE * psf)91 double64_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
283 double
double64_be_read(const unsigned char * cptr)284 double64_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
316 double
double64_le_read(const unsigned char * cptr)317 double64_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
349 void
double64_be_write(double in,unsigned char * out)350 double64_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
389 void
double64_le_write(double in,unsigned char * out)390 double64_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
433 static void
double64_peak_update(SF_PRIVATE * psf,const double * buffer,int count,sf_count_t indx)434 double64_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
457 static int
double64_get_capability(SF_PRIVATE * psf)458 double64_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
487 static void
d2s_array(const double * src,int count,short * dest,double scale)488 d2s_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
494 static void
d2s_clip_array(const double * src,int count,short * dest,double scale)495 d2s_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
508 static void
d2i_array(const double * src,int count,int * dest,double scale)509 d2i_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
515 static void
d2i_clip_array(const double * src,int count,int * dest,double scale)516 d2i_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
529 static inline void
d2f_array(const double * src,int count,float * dest)530 d2f_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
536 static inline void
s2d_array(const short * src,double * dest,int count,double scale)537 s2d_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
543 static inline void
i2d_array(const int * src,double * dest,int count,double scale)544 i2d_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
550 static inline void
f2d_array(const float * src,double * dest,int count)551 f2d_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
560 static sf_count_t
host_read_d2s(SF_PRIVATE * psf,short * ptr,sf_count_t len)561 host_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
590 static sf_count_t
host_read_d2i(SF_PRIVATE * psf,int * ptr,sf_count_t len)591 host_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
620 static sf_count_t
host_read_d2f(SF_PRIVATE * psf,float * ptr,sf_count_t len)621 host_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
646 static sf_count_t
host_read_d(SF_PRIVATE * psf,double * ptr,sf_count_t len)647 host_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
676 static sf_count_t
host_write_s2d(SF_PRIVATE * psf,const short * ptr,sf_count_t len)677 host_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
708 static sf_count_t
host_write_i2d(SF_PRIVATE * psf,const int * ptr,sf_count_t len)709 host_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
739 static sf_count_t
host_write_f2d(SF_PRIVATE * psf,const float * ptr,sf_count_t len)740 host_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
768 static sf_count_t
host_write_d(SF_PRIVATE * psf,const double * ptr,sf_count_t len)769 host_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
801 static sf_count_t
replace_read_d2s(SF_PRIVATE * psf,short * ptr,sf_count_t len)802 replace_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
831 static sf_count_t
replace_read_d2i(SF_PRIVATE * psf,int * ptr,sf_count_t len)832 replace_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
861 static sf_count_t
replace_read_d2f(SF_PRIVATE * psf,float * ptr,sf_count_t len)862 replace_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
890 static sf_count_t
replace_read_d(SF_PRIVATE * psf,double * ptr,sf_count_t len)891 replace_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
920 static sf_count_t
replace_write_s2d(SF_PRIVATE * psf,const short * ptr,sf_count_t len)921 replace_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
953 static sf_count_t
replace_write_i2d(SF_PRIVATE * psf,const int * ptr,sf_count_t len)954 replace_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
986 static sf_count_t
replace_write_f2d(SF_PRIVATE * psf,const float * ptr,sf_count_t len)987 replace_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
1014 static sf_count_t
replace_write_d(SF_PRIVATE * psf,const double * ptr,sf_count_t len)1015 replace_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
1050 static void
d2bd_read(double * buffer,int count)1051 d2bd_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
1057 static void
bd2d_write(double * buffer,int count)1058 bd2d_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