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 {	while (--count >= 0)
490 	{	dest [count] = psf_lrint (scale * src [count]) ;
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 {	while (--count >= 0)
497 	{	double tmp = scale * src [count] ;
498 
499 		if (CPU_CLIPS_POSITIVE == 0 && tmp > 32767.0)
500 			dest [count] = SHRT_MAX ;
501 		else if (CPU_CLIPS_NEGATIVE == 0 && tmp < -32768.0)
502 			dest [count] = SHRT_MIN ;
503 		else
504 			dest [count] = 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 {	while (--count >= 0)
511 	{	dest [count] = psf_lrint (scale * src [count]) ;
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 {	while (--count >= 0)
518 	{	float tmp = scale * src [count] ;
519 
520 		if (CPU_CLIPS_POSITIVE == 0 && tmp > (1.0 * INT_MAX))
521 			dest [count] = INT_MAX ;
522 		else if (CPU_CLIPS_NEGATIVE == 0 && tmp < (-1.0 * INT_MAX))
523 			dest [count] = INT_MIN ;
524 		else
525 			dest [count] = 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 {	while (--count >= 0)
532 	{	dest [count] = src [count] ;
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 {	while (--count >= 0)
539 	{	dest [count] = scale * src [count] ;
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 {	while (--count >= 0)
546 	{	dest [count] = scale * src [count] ;
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 {	while (--count >= 0)
553 	{	dest [count] = src [count] ;
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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 {	while (--count >= 0)
1053 	{	buffer [count] = DOUBLE64_READ ((unsigned char *) (buffer + count)) ;
1054 		} ;
1055 } /* d2bd_read */
1056 
1057 static void
bd2d_write(double * buffer,int count)1058 bd2d_write (double *buffer, int count)
1059 {	while (--count >= 0)
1060 	{	DOUBLE64_WRITE (buffer [count], (unsigned char*) (buffer + count)) ;
1061 		} ;
1062 } /* bd2d_write */
1063 
1064