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