blob: 425088bb3ea8f2f3b3eaa7ebcc784757fc163bd4 [file] [log] [blame]
Alexandre Lision7c6f4a62013-09-05 13:27:01 -04001/*
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
47enum
48{ DOUBLE_UNKNOWN = 0x00,
49 DOUBLE_CAN_RW_LE = 0x23,
50 DOUBLE_CAN_RW_BE = 0x34,
51 DOUBLE_BROKEN_LE = 0x45,
52 DOUBLE_BROKEN_BE = 0x56
53} ;
54
55/*--------------------------------------------------------------------------------------------
56** Prototypes for private functions.
57*/
58
59static sf_count_t host_read_d2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
60static sf_count_t host_read_d2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
61static sf_count_t host_read_d2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
62static sf_count_t host_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
63
64static sf_count_t host_write_s2d (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
65static sf_count_t host_write_i2d (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
66static sf_count_t host_write_f2d (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
67static sf_count_t host_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
68
69static void double64_peak_update (SF_PRIVATE *psf, const double *buffer, int count, sf_count_t indx) ;
70
71static int double64_get_capability (SF_PRIVATE *psf) ;
72
73static sf_count_t replace_read_d2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
74static sf_count_t replace_read_d2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
75static sf_count_t replace_read_d2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
76static sf_count_t replace_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
77
78static sf_count_t replace_write_s2d (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
79static sf_count_t replace_write_i2d (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
80static sf_count_t replace_write_f2d (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
81static sf_count_t replace_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
82
83static void d2bd_read (double *buffer, int count) ;
84static void bd2d_write (double *buffer, int count) ;
85
86/*--------------------------------------------------------------------------------------------
87** Exported functions.
88*/
89
90int
91double64_init (SF_PRIVATE *psf)
92{ static int double64_caps ;
93
94 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
278double
279double64_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
311double
312double64_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
344void
345double64_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
384void
385double64_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
428static void
429double64_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
452static int
453double64_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
482static void
483d2s_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
489static void
490d2s_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
503static void
504d2i_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
510static void
511d2i_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
524static inline void
525d2f_array (const double *src, int count, float *dest)
526{ while (--count >= 0)
527 { dest [count] = src [count] ;
528 } ;
529} /* d2f_array */
530
531static inline void
532s2d_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
538static inline void
539i2d_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
545static inline void
546f2d_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
555static sf_count_t
556host_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
584static sf_count_t
585host_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
613static sf_count_t
614host_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
638static sf_count_t
639host_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
668static sf_count_t
669host_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
699static sf_count_t
700host_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
729static sf_count_t
730host_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
757static sf_count_t
758host_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
789static sf_count_t
790replace_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
818static sf_count_t
819replace_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
847static sf_count_t
848replace_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
875static sf_count_t
876replace_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
904static sf_count_t
905replace_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
936static sf_count_t
937replace_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
968static sf_count_t
969replace_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
995static sf_count_t
996replace_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
1030static void
1031d2bd_read (double *buffer, int count)
1032{ while (--count >= 0)
1033 { buffer [count] = DOUBLE64_READ ((unsigned char *) (buffer + count)) ;
1034 } ;
1035} /* d2bd_read */
1036
1037static void
1038bd2d_write (double *buffer, int count)
1039{ while (--count >= 0)
1040 { DOUBLE64_WRITE (buffer [count], (unsigned char*) (buffer + count)) ;
1041 } ;
1042} /* bd2d_write */
1043