xref: /third_party/libsnd/src/float32.c (revision b815c7f3)
1/*
2** Copyright (C) 1999-2017 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 FLOAT32_READ	float32_le_read
33	#define FLOAT32_WRITE	float32_le_write
34#elif CPU_IS_BIG_ENDIAN
35	#define FLOAT32_READ	float32_be_read
36	#define FLOAT32_WRITE	float32_be_write
37#endif
38
39/*--------------------------------------------------------------------------------------------
40**	Processor floating point capabilities. float32_get_capability () returns one of the
41**	latter four values.
42*/
43
44enum
45{	FLOAT_UNKNOWN		= 0x00,
46	FLOAT_CAN_RW_LE		= 0x12,
47	FLOAT_CAN_RW_BE		= 0x23,
48	FLOAT_BROKEN_LE		= 0x34,
49	FLOAT_BROKEN_BE		= 0x45
50} ;
51
52/*--------------------------------------------------------------------------------------------
53**	Prototypes for private functions.
54*/
55
56static sf_count_t	host_read_f2s	(SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
57static sf_count_t	host_read_f2i	(SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
58static sf_count_t	host_read_f	(SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
59static sf_count_t	host_read_f2d	(SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
60
61static sf_count_t	host_write_s2f	(SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
62static sf_count_t	host_write_i2f	(SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
63static sf_count_t	host_write_f	(SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
64static sf_count_t	host_write_d2f	(SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
65
66static void		float32_peak_update	(SF_PRIVATE *psf, const float *buffer, int count, sf_count_t indx) ;
67
68static sf_count_t	replace_read_f2s	(SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
69static sf_count_t	replace_read_f2i	(SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
70static sf_count_t	replace_read_f	(SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
71static sf_count_t	replace_read_f2d	(SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
72
73static sf_count_t	replace_write_s2f	(SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
74static sf_count_t	replace_write_i2f	(SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
75static sf_count_t	replace_write_f	(SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
76static sf_count_t	replace_write_d2f	(SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
77
78static	void	bf2f_array (float *buffer, int count) ;
79static	void	f2bf_array (float *buffer, int count) ;
80
81static int		float32_get_capability	(SF_PRIVATE *psf) ;
82
83/*--------------------------------------------------------------------------------------------
84**	Exported functions.
85*/
86
87int
88float32_init	(SF_PRIVATE *psf)
89{	static int float_caps ;
90
91	if (psf->sf.channels < 1)
92	{	psf_log_printf (psf, "float32_init : internal error : channels = %d\n", psf->sf.channels) ;
93		return SFE_INTERNAL ;
94		} ;
95
96	float_caps = float32_get_capability (psf) ;
97
98	psf->blockwidth = sizeof (float) * psf->sf.channels ;
99
100	if (psf->file.mode == SFM_READ || psf->file.mode == SFM_RDWR)
101	{	switch (psf->endian + float_caps)
102		{	case (SF_ENDIAN_BIG + FLOAT_CAN_RW_BE) :
103					psf->data_endswap = SF_FALSE ;
104					psf->read_short		= host_read_f2s ;
105					psf->read_int		= host_read_f2i ;
106					psf->read_float		= host_read_f ;
107					psf->read_double	= host_read_f2d ;
108					break ;
109
110			case (SF_ENDIAN_LITTLE + FLOAT_CAN_RW_LE) :
111					psf->data_endswap = SF_FALSE ;
112					psf->read_short		= host_read_f2s ;
113					psf->read_int		= host_read_f2i ;
114					psf->read_float		= host_read_f ;
115					psf->read_double	= host_read_f2d ;
116					break ;
117
118			case (SF_ENDIAN_BIG + FLOAT_CAN_RW_LE) :
119					psf->data_endswap = SF_TRUE ;
120					psf->read_short		= host_read_f2s ;
121					psf->read_int		= host_read_f2i ;
122					psf->read_float		= host_read_f ;
123					psf->read_double	= host_read_f2d ;
124					break ;
125
126			case (SF_ENDIAN_LITTLE + FLOAT_CAN_RW_BE) :
127					psf->data_endswap = SF_TRUE ;
128					psf->read_short		= host_read_f2s ;
129					psf->read_int		= host_read_f2i ;
130					psf->read_float		= host_read_f ;
131					psf->read_double	= host_read_f2d ;
132					break ;
133
134			/* When the CPU is not IEEE compatible. */
135			case (SF_ENDIAN_BIG + FLOAT_BROKEN_LE) :
136					psf->data_endswap = SF_TRUE ;
137					psf->read_short		= replace_read_f2s ;
138					psf->read_int		= replace_read_f2i ;
139					psf->read_float		= replace_read_f ;
140					psf->read_double	= replace_read_f2d ;
141					break ;
142
143			case (SF_ENDIAN_LITTLE + FLOAT_BROKEN_LE) :
144					psf->data_endswap = SF_FALSE ;
145					psf->read_short		= replace_read_f2s ;
146					psf->read_int		= replace_read_f2i ;
147					psf->read_float		= replace_read_f ;
148					psf->read_double	= replace_read_f2d ;
149					break ;
150
151			case (SF_ENDIAN_BIG + FLOAT_BROKEN_BE) :
152					psf->data_endswap = SF_FALSE ;
153					psf->read_short		= replace_read_f2s ;
154					psf->read_int		= replace_read_f2i ;
155					psf->read_float		= replace_read_f ;
156					psf->read_double	= replace_read_f2d ;
157					break ;
158
159			case (SF_ENDIAN_LITTLE + FLOAT_BROKEN_BE) :
160					psf->data_endswap = SF_TRUE ;
161					psf->read_short		= replace_read_f2s ;
162					psf->read_int		= replace_read_f2i ;
163					psf->read_float		= replace_read_f ;
164					psf->read_double	= replace_read_f2d ;
165					break ;
166
167			default : break ;
168			} ;
169		} ;
170
171	if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
172	{	switch (psf->endian + float_caps)
173		{	case (SF_ENDIAN_LITTLE + FLOAT_CAN_RW_LE) :
174					psf->data_endswap = SF_FALSE ;
175					psf->write_short	= host_write_s2f ;
176					psf->write_int		= host_write_i2f ;
177					psf->write_float	= host_write_f ;
178					psf->write_double	= host_write_d2f ;
179					break ;
180
181			case (SF_ENDIAN_BIG + FLOAT_CAN_RW_BE) :
182					psf->data_endswap = SF_FALSE ;
183					psf->write_short	= host_write_s2f ;
184					psf->write_int		= host_write_i2f ;
185					psf->write_float	= host_write_f ;
186					psf->write_double	= host_write_d2f ;
187					break ;
188
189			case (SF_ENDIAN_BIG + FLOAT_CAN_RW_LE) :
190					psf->data_endswap = SF_TRUE ;
191					psf->write_short	= host_write_s2f ;
192					psf->write_int		= host_write_i2f ;
193					psf->write_float	= host_write_f ;
194					psf->write_double	= host_write_d2f ;
195					break ;
196
197			case (SF_ENDIAN_LITTLE + FLOAT_CAN_RW_BE) :
198					psf->data_endswap = SF_TRUE ;
199					psf->write_short	= host_write_s2f ;
200					psf->write_int		= host_write_i2f ;
201					psf->write_float	= host_write_f ;
202					psf->write_double	= host_write_d2f ;
203					break ;
204
205			/* When the CPU is not IEEE compatible. */
206			case (SF_ENDIAN_BIG + FLOAT_BROKEN_LE) :
207					psf->data_endswap = SF_TRUE ;
208					psf->write_short	= replace_write_s2f ;
209					psf->write_int		= replace_write_i2f ;
210					psf->write_float	= replace_write_f ;
211					psf->write_double	= replace_write_d2f ;
212					break ;
213
214			case (SF_ENDIAN_LITTLE + FLOAT_BROKEN_LE) :
215					psf->data_endswap = SF_FALSE ;
216					psf->write_short	= replace_write_s2f ;
217					psf->write_int		= replace_write_i2f ;
218					psf->write_float	= replace_write_f ;
219					psf->write_double	= replace_write_d2f ;
220					break ;
221
222			case (SF_ENDIAN_BIG + FLOAT_BROKEN_BE) :
223					psf->data_endswap = SF_FALSE ;
224					psf->write_short	= replace_write_s2f ;
225					psf->write_int		= replace_write_i2f ;
226					psf->write_float	= replace_write_f ;
227					psf->write_double	= replace_write_d2f ;
228					break ;
229
230			case (SF_ENDIAN_LITTLE + FLOAT_BROKEN_BE) :
231					psf->data_endswap = SF_TRUE ;
232					psf->write_short	= replace_write_s2f ;
233					psf->write_int		= replace_write_i2f ;
234					psf->write_float	= replace_write_f ;
235					psf->write_double	= replace_write_d2f ;
236					break ;
237
238			default : break ;
239			} ;
240		} ;
241
242	if (psf->filelength > psf->dataoffset)
243	{	psf->datalength = (psf->dataend > 0) ? psf->dataend - psf->dataoffset :
244							psf->filelength - psf->dataoffset ;
245		}
246	else
247		psf->datalength = 0 ;
248
249	psf->sf.frames = psf->blockwidth > 0 ? psf->datalength / psf->blockwidth : 0 ;
250
251	return 0 ;
252} /* float32_init */
253
254float
255float32_be_read (const unsigned char *cptr)
256{	int		exponent, mantissa, negative ;
257	float	fvalue ;
258
259	negative = cptr [0] & 0x80 ;
260	exponent = ((cptr [0] & 0x7F) << 1) | ((cptr [1] & 0x80) ? 1 : 0) ;
261	mantissa = ((cptr [1] & 0x7F) << 16) | (cptr [2] << 8) | (cptr [3]) ;
262
263	if (! (exponent || mantissa))
264		return 0.0 ;
265
266	mantissa |= 0x800000 ;
267	exponent = exponent ? exponent - 127 : 0 ;
268
269	fvalue = mantissa ? ((float) mantissa) / ((float) 0x800000) : 0.0 ;
270
271	if (negative)
272		fvalue *= -1 ;
273
274	if (exponent > 0)
275		fvalue *= pow (2.0, exponent) ;
276	else if (exponent < 0)
277		fvalue /= pow (2.0, abs (exponent)) ;
278
279	return fvalue ;
280} /* float32_be_read */
281
282float
283float32_le_read (const unsigned char *cptr)
284{	int		exponent, mantissa, negative ;
285	float	fvalue ;
286
287	negative = cptr [3] & 0x80 ;
288	exponent = ((cptr [3] & 0x7F) << 1) | ((cptr [2] & 0x80) ? 1 : 0) ;
289	mantissa = ((cptr [2] & 0x7F) << 16) | (cptr [1] << 8) | (cptr [0]) ;
290
291	if (! (exponent || mantissa))
292		return 0.0 ;
293
294	mantissa |= 0x800000 ;
295	exponent = exponent ? exponent - 127 : 0 ;
296
297	fvalue = mantissa ? ((float) mantissa) / ((float) 0x800000) : 0.0 ;
298
299	if (negative)
300		fvalue *= -1 ;
301
302	if (exponent > 0)
303		fvalue *= pow (2.0, exponent) ;
304	else if (exponent < 0)
305		fvalue /= pow (2.0, abs (exponent)) ;
306
307	return fvalue ;
308} /* float32_le_read */
309
310void
311float32_le_write (float in, unsigned char *out)
312{	int		exponent, mantissa, negative = 0 ;
313
314	memset (out, 0, sizeof (int)) ;
315
316	if (fabs (in) < 1e-30)
317		return ;
318
319	if (in < 0.0)
320	{	in *= -1.0 ;
321		negative = 1 ;
322		} ;
323
324	in = frexp (in, &exponent) ;
325
326	exponent += 126 ;
327
328	in *= (float) 0x1000000 ;
329	mantissa = (((int) in) & 0x7FFFFF) ;
330
331	if (negative)
332		out [3] |= 0x80 ;
333
334	if (exponent & 0x01)
335		out [2] |= 0x80 ;
336
337	out [0] = mantissa & 0xFF ;
338	out [1] = (mantissa >> 8) & 0xFF ;
339	out [2] |= (mantissa >> 16) & 0x7F ;
340	out [3] |= (exponent >> 1) & 0x7F ;
341
342	return ;
343} /* float32_le_write */
344
345void
346float32_be_write (float in, unsigned char *out)
347{	int		exponent, mantissa, negative = 0 ;
348
349	memset (out, 0, sizeof (int)) ;
350
351	if (fabs (in) < 1e-30)
352		return ;
353
354	if (in < 0.0)
355	{	in *= -1.0 ;
356		negative = 1 ;
357		} ;
358
359	in = frexp (in, &exponent) ;
360
361	exponent += 126 ;
362
363	in *= (float) 0x1000000 ;
364	mantissa = (((int) in) & 0x7FFFFF) ;
365
366	if (negative)
367		out [0] |= 0x80 ;
368
369	if (exponent & 0x01)
370		out [1] |= 0x80 ;
371
372	out [3] = mantissa & 0xFF ;
373	out [2] = (mantissa >> 8) & 0xFF ;
374	out [1] |= (mantissa >> 16) & 0x7F ;
375	out [0] |= (exponent >> 1) & 0x7F ;
376
377	return ;
378} /* float32_be_write */
379
380/*==============================================================================================
381**	Private functions.
382*/
383
384static void
385float32_peak_update	(SF_PRIVATE *psf, const float *buffer, int count, sf_count_t indx)
386{	int 	chan ;
387	int		k, position ;
388	float	fmaxval ;
389
390	for (chan = 0 ; chan < psf->sf.channels ; chan++)
391	{	fmaxval = fabs (buffer [chan]) ;
392		position = 0 ;
393		for (k = chan ; k < count ; k += psf->sf.channels)
394			if (fmaxval < fabs (buffer [k]))
395			{	fmaxval = fabs (buffer [k]) ;
396				position = k ;
397				} ;
398
399		if (fmaxval > psf->peak_info->peaks [chan].value)
400		{	psf->peak_info->peaks [chan].value = fmaxval ;
401			psf->peak_info->peaks [chan].position = psf->write_current + indx + (position / psf->sf.channels) ;
402			} ;
403		} ;
404
405	return ;
406} /* float32_peak_update */
407
408static int
409float32_get_capability	(SF_PRIVATE *psf)
410{	union
411	{	float			f ;
412		int				i ;
413		unsigned char	c [4] ;
414	} data ;
415
416	data.f = (float) 1.23456789 ; /* Some abitrary value. */
417
418	if (! psf->ieee_replace)
419	{	/* If this test is true ints and floats are compatible and little endian. */
420		if (data.c [0] == 0x52 && data.c [1] == 0x06 && data.c [2] == 0x9e && data.c [3] == 0x3f)
421			return FLOAT_CAN_RW_LE ;
422
423		/* If this test is true ints and floats are compatible and big endian. */
424		if (data.c [3] == 0x52 && data.c [2] == 0x06 && data.c [1] == 0x9e && data.c [0] == 0x3f)
425			return FLOAT_CAN_RW_BE ;
426		} ;
427
428	/* Floats are broken. Don't expect reading or writing to be fast. */
429	psf_log_printf (psf, "Using IEEE replacement code for float.\n") ;
430
431	return (CPU_IS_LITTLE_ENDIAN) ? FLOAT_BROKEN_LE : FLOAT_BROKEN_BE ;
432} /* float32_get_capability */
433
434/*=======================================================================================
435*/
436
437static void
438f2s_array (const float *src, int count, short *dest, float scale)
439{
440	for (int i = 0 ; i < count ; i++)
441	{	dest [i] = psf_lrintf (scale * src [i]) ;
442		} ;
443} /* f2s_array */
444
445static void
446f2s_clip_array (const float *src, int count, short *dest, float scale)
447{	for (int i = 0 ; i < count ; i++)
448	{	float tmp = scale * src [i] ;
449
450		if (tmp > 32767.0)
451			dest [i] = SHRT_MAX ;
452		else if (tmp < -32768.0)
453			dest [i] = SHRT_MIN ;
454		else
455			dest [i] = psf_lrintf (tmp) ;
456		} ;
457} /* f2s_clip_array */
458
459static inline void
460f2i_array (const float *src, int count, int *dest, float scale)
461{	for (int i = 0 ; i < count ; i++)
462	{	dest [i] = psf_lrintf (scale * src [i]) ;
463		} ;
464} /* f2i_array */
465
466static inline void
467f2i_clip_array (const float *src, int count, int *dest, float scale)
468{	for (int i = 0 ; i < count ; i++)
469	{	float tmp = scale * src [i] ;
470
471		if (CPU_CLIPS_POSITIVE == 0 && tmp > (1.0 * INT_MAX))
472			dest [i] = INT_MAX ;
473		else if (CPU_CLIPS_NEGATIVE == 0 && tmp < (-1.0 * INT_MAX))
474			dest [i] = INT_MIN ;
475		else
476			dest [i] = psf_lrintf (tmp) ;
477		} ;
478} /* f2i_clip_array */
479
480static inline void
481f2d_array (const float *src, int count, double *dest)
482{	for (int i = 0 ; i < count ; i++)
483	{	dest [i] = src [i] ;
484		} ;
485} /* f2d_array */
486
487static inline void
488s2f_array (const short *src, float *dest, int count, float scale)
489{	for (int i = 0 ; i < count ; i++)
490	{	dest [i] = scale * src [i] ;
491		} ;
492} /* s2f_array */
493
494static inline void
495i2f_array (const int *src, float *dest, int count, float scale)
496{	for (int i = 0 ; i < count ; i++)
497	{	dest [i] = scale * src [i] ;
498		} ;
499} /* i2f_array */
500
501static inline void
502d2f_array (const double *src, float *dest, int count)
503{	for (int i = 0 ; i < count ; i++)
504	{	dest [i] = src [i] ;
505		} ;
506} /* d2f_array */
507
508/*----------------------------------------------------------------------------------------------
509*/
510
511static sf_count_t
512host_read_f2s	(SF_PRIVATE *psf, short *ptr, sf_count_t len)
513{	BUF_UNION	ubuf ;
514	void		(*convert) (const float *, int, short *, float) ;
515	int			bufferlen, readcount ;
516	sf_count_t	total = 0 ;
517	float		scale ;
518
519	convert = (psf->add_clipping) ? f2s_clip_array : f2s_array ;
520	bufferlen = ARRAY_LEN (ubuf.fbuf) ;
521	scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFF / psf->float_max ;
522
523	while (len > 0)
524	{	if (len < bufferlen)
525			bufferlen = (int) len ;
526		readcount = (int) psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
527
528/* Fix me : Need lef2s_array */
529		if (psf->data_endswap == SF_TRUE)
530			endswap_int_array (ubuf.ibuf, readcount) ;
531
532		convert (ubuf.fbuf, readcount, ptr + total, scale) ;
533		total += readcount ;
534		if (readcount < bufferlen)
535			break ;
536		len -= readcount ;
537		} ;
538
539	return total ;
540} /* host_read_f2s */
541
542static sf_count_t
543host_read_f2i	(SF_PRIVATE *psf, int *ptr, sf_count_t len)
544{	BUF_UNION	ubuf ;
545	void		(*convert) (const float *, int, int *, float) ;
546	int			bufferlen, readcount ;
547	sf_count_t	total = 0 ;
548	float		scale ;
549
550	convert = (psf->add_clipping) ? f2i_clip_array : f2i_array ;
551	bufferlen = ARRAY_LEN (ubuf.fbuf) ;
552	scale = (psf->float_int_mult == 0) ? 1.0 : 2147483648.0f / psf->float_max ;
553
554	while (len > 0)
555	{	if (len < bufferlen)
556			bufferlen = (int) len ;
557		readcount = (int) psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
558
559		if (psf->data_endswap == SF_TRUE)
560			endswap_int_array (ubuf.ibuf, bufferlen) ;
561
562		convert (ubuf.fbuf, readcount, ptr + total, scale) ;
563		total += readcount ;
564		if (readcount < bufferlen)
565			break ;
566		len -= readcount ;
567		} ;
568
569	return total ;
570} /* host_read_f2i */
571
572static sf_count_t
573host_read_f	(SF_PRIVATE *psf, float *ptr, sf_count_t len)
574{	BUF_UNION	ubuf ;
575	int			bufferlen, readcount ;
576	sf_count_t	total = 0 ;
577
578	if (psf->data_endswap != SF_TRUE)
579		return psf_fread (ptr, sizeof (float), len, psf) ;
580
581	bufferlen = ARRAY_LEN (ubuf.fbuf) ;
582
583	while (len > 0)
584	{	if (len < bufferlen)
585			bufferlen = (int) len ;
586		readcount = (int) psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
587
588		endswap_int_copy ((int*) (ptr + total), ubuf.ibuf, readcount) ;
589
590		total += readcount ;
591		if (readcount < bufferlen)
592			break ;
593		len -= readcount ;
594		} ;
595
596	return total ;
597} /* host_read_f */
598
599static sf_count_t
600host_read_f2d	(SF_PRIVATE *psf, double *ptr, sf_count_t len)
601{	BUF_UNION	ubuf ;
602	int			bufferlen, readcount ;
603	sf_count_t	total = 0 ;
604
605	bufferlen = ARRAY_LEN (ubuf.fbuf) ;
606
607	while (len > 0)
608	{	if (len < bufferlen)
609			bufferlen = (int) len ;
610		readcount = (int) psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
611
612		if (psf->data_endswap == SF_TRUE)
613			endswap_int_array (ubuf.ibuf, bufferlen) ;
614
615/* Fix me : Need lef2d_array */
616		f2d_array (ubuf.fbuf, readcount, ptr + total) ;
617		total += readcount ;
618		if (readcount < bufferlen)
619			break ;
620		len -= readcount ;
621		} ;
622
623	return total ;
624} /* host_read_f2d */
625
626static sf_count_t
627host_write_s2f	(SF_PRIVATE *psf, const short *ptr, sf_count_t len)
628{	BUF_UNION	ubuf ;
629	int			bufferlen, writecount ;
630	sf_count_t	total = 0 ;
631	float		scale ;
632
633/* Erik */
634	scale = (psf->scale_int_float == 0) ? 1.0 : 1.0 / 0x8000 ;
635	bufferlen = ARRAY_LEN (ubuf.fbuf) ;
636
637	while (len > 0)
638	{	if (len < bufferlen)
639			bufferlen = (int) len ;
640		s2f_array (ptr + total, ubuf.fbuf, bufferlen, scale) ;
641
642		if (psf->peak_info)
643			float32_peak_update (psf, ubuf.fbuf, bufferlen, total / psf->sf.channels) ;
644
645		if (psf->data_endswap == SF_TRUE)
646			endswap_int_array (ubuf.ibuf, bufferlen) ;
647
648		writecount = (int) psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
649		total += writecount ;
650		if (writecount < bufferlen)
651			break ;
652		len -= writecount ;
653		} ;
654
655	return total ;
656} /* host_write_s2f */
657
658static sf_count_t
659host_write_i2f	(SF_PRIVATE *psf, const int *ptr, sf_count_t len)
660{	BUF_UNION	ubuf ;
661	int			bufferlen, writecount ;
662	sf_count_t	total = 0 ;
663	float		scale ;
664
665	scale = (psf->scale_int_float == 0) ? 1.0 : 1.0 / (8.0 * 0x10000000) ;
666	bufferlen = ARRAY_LEN (ubuf.fbuf) ;
667
668	while (len > 0)
669	{	if (len < bufferlen)
670			bufferlen = (int) len ;
671		i2f_array (ptr + total, ubuf.fbuf, bufferlen, scale) ;
672
673		if (psf->peak_info)
674			float32_peak_update (psf, ubuf.fbuf, bufferlen, total / psf->sf.channels) ;
675
676		if (psf->data_endswap == SF_TRUE)
677			endswap_int_array (ubuf.ibuf, bufferlen) ;
678
679		writecount = (int) psf_fwrite (ubuf.fbuf, sizeof (float) , bufferlen, psf) ;
680		total += writecount ;
681		if (writecount < bufferlen)
682			break ;
683		len -= writecount ;
684		} ;
685
686	return total ;
687} /* host_write_i2f */
688
689static sf_count_t
690host_write_f	(SF_PRIVATE *psf, const float *ptr, sf_count_t len)
691{	BUF_UNION	ubuf ;
692	int			bufferlen, writecount ;
693	sf_count_t	total = 0 ;
694
695	if (psf->peak_info)
696		float32_peak_update (psf, ptr, len, 0) ;
697
698	if (psf->data_endswap != SF_TRUE)
699		return psf_fwrite (ptr, sizeof (float), len, psf) ;
700
701	bufferlen = ARRAY_LEN (ubuf.fbuf) ;
702
703	while (len > 0)
704	{	if (len < bufferlen)
705			bufferlen = (int) len ;
706
707		endswap_int_copy (ubuf.ibuf, (const int*) (ptr + total), bufferlen) ;
708
709		writecount = (int) psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
710		total += writecount ;
711		if (writecount < bufferlen)
712			break ;
713		len -= writecount ;
714		} ;
715
716	return total ;
717} /* host_write_f */
718
719static sf_count_t
720host_write_d2f	(SF_PRIVATE *psf, const double *ptr, sf_count_t len)
721{	BUF_UNION	ubuf ;
722	int			bufferlen, writecount ;
723	sf_count_t	total = 0 ;
724
725	bufferlen = ARRAY_LEN (ubuf.fbuf) ;
726
727	while (len > 0)
728	{	if (len < bufferlen)
729			bufferlen = (int) len ;
730
731		d2f_array (ptr + total, ubuf.fbuf, bufferlen) ;
732
733		if (psf->peak_info)
734			float32_peak_update (psf, ubuf.fbuf, bufferlen, total / psf->sf.channels) ;
735
736		if (psf->data_endswap == SF_TRUE)
737			endswap_int_array (ubuf.ibuf, bufferlen) ;
738
739		writecount = (int) psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
740		total += writecount ;
741		if (writecount < bufferlen)
742			break ;
743		len -= writecount ;
744		} ;
745
746	return total ;
747} /* host_write_d2f */
748
749/*=======================================================================================
750*/
751
752static sf_count_t
753replace_read_f2s	(SF_PRIVATE *psf, short *ptr, sf_count_t len)
754{	BUF_UNION	ubuf ;
755	int			bufferlen, readcount ;
756	sf_count_t	total = 0 ;
757	float		scale ;
758
759	bufferlen = ARRAY_LEN (ubuf.fbuf) ;
760	scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFF / psf->float_max ;
761
762	while (len > 0)
763	{	if (len < bufferlen)
764			bufferlen = (int) len ;
765		readcount = (int) psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
766
767		if (psf->data_endswap == SF_TRUE)
768			endswap_int_array (ubuf.ibuf, bufferlen) ;
769
770		bf2f_array (ubuf.fbuf, bufferlen) ;
771
772		f2s_array (ubuf.fbuf, readcount, ptr + total, scale) ;
773		total += readcount ;
774		if (readcount < bufferlen)
775			break ;
776		len -= readcount ;
777		} ;
778
779	return total ;
780} /* replace_read_f2s */
781
782static sf_count_t
783replace_read_f2i	(SF_PRIVATE *psf, int *ptr, sf_count_t len)
784{	BUF_UNION	ubuf ;
785	int			bufferlen, readcount ;
786	sf_count_t	total = 0 ;
787	float		scale ;
788
789	bufferlen = ARRAY_LEN (ubuf.fbuf) ;
790	scale = (psf->float_int_mult == 0) ? 1.0 : 2147483648.0f / psf->float_max ;
791
792	while (len > 0)
793	{	if (len < bufferlen)
794			bufferlen = (int) len ;
795		readcount = (int) psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
796
797		if (psf->data_endswap == SF_TRUE)
798			endswap_int_array (ubuf.ibuf, bufferlen) ;
799
800		bf2f_array (ubuf.fbuf, bufferlen) ;
801
802		f2i_array (ubuf.fbuf, readcount, ptr + total, scale) ;
803		total += readcount ;
804		if (readcount < bufferlen)
805			break ;
806		len -= readcount ;
807		} ;
808
809	return total ;
810} /* replace_read_f2i */
811
812static sf_count_t
813replace_read_f	(SF_PRIVATE *psf, float *ptr, sf_count_t len)
814{	BUF_UNION	ubuf ;
815	int			bufferlen, readcount ;
816	sf_count_t	total = 0 ;
817
818	/* FIX THIS */
819
820	bufferlen = ARRAY_LEN (ubuf.fbuf) ;
821
822	while (len > 0)
823	{	if (len < bufferlen)
824			bufferlen = (int) len ;
825		readcount = (int) psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
826
827		if (psf->data_endswap == SF_TRUE)
828			endswap_int_array (ubuf.ibuf, bufferlen) ;
829
830		bf2f_array (ubuf.fbuf, bufferlen) ;
831
832		memcpy (ptr + total, ubuf.fbuf, bufferlen * sizeof (float)) ;
833
834		total += readcount ;
835		if (readcount < bufferlen)
836			break ;
837		len -= readcount ;
838		} ;
839
840	return total ;
841} /* replace_read_f */
842
843static sf_count_t
844replace_read_f2d	(SF_PRIVATE *psf, double *ptr, sf_count_t len)
845{	BUF_UNION	ubuf ;
846	int			bufferlen, readcount ;
847	sf_count_t	total = 0 ;
848
849	bufferlen = ARRAY_LEN (ubuf.fbuf) ;
850
851	while (len > 0)
852	{	if (len < bufferlen)
853			bufferlen = (int) len ;
854		readcount = (int) psf_fread (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
855
856		if (psf->data_endswap == SF_TRUE)
857			endswap_int_array (ubuf.ibuf, bufferlen) ;
858
859		bf2f_array (ubuf.fbuf, bufferlen) ;
860
861		f2d_array (ubuf.fbuf, readcount, ptr + total) ;
862		total += readcount ;
863		if (readcount < bufferlen)
864			break ;
865		len -= readcount ;
866		} ;
867
868	return total ;
869} /* replace_read_f2d */
870
871static sf_count_t
872replace_write_s2f	(SF_PRIVATE *psf, const short *ptr, sf_count_t len)
873{	BUF_UNION	ubuf ;
874	int			bufferlen, writecount ;
875	sf_count_t	total = 0 ;
876	float		scale ;
877
878	scale = (psf->scale_int_float == 0) ? 1.0 : 1.0 / 0x8000 ;
879	bufferlen = ARRAY_LEN (ubuf.fbuf) ;
880
881	while (len > 0)
882	{	if (len < bufferlen)
883			bufferlen = (int) len ;
884		s2f_array (ptr + total, ubuf.fbuf, bufferlen, scale) ;
885
886		if (psf->peak_info)
887			float32_peak_update (psf, ubuf.fbuf, bufferlen, total / psf->sf.channels) ;
888
889		f2bf_array (ubuf.fbuf, bufferlen) ;
890
891		if (psf->data_endswap == SF_TRUE)
892			endswap_int_array (ubuf.ibuf, bufferlen) ;
893
894		writecount = (int) psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
895		total += writecount ;
896		if (writecount < bufferlen)
897			break ;
898		len -= writecount ;
899		} ;
900
901	return total ;
902} /* replace_write_s2f */
903
904static sf_count_t
905replace_write_i2f	(SF_PRIVATE *psf, const int *ptr, sf_count_t len)
906{	BUF_UNION	ubuf ;
907	int			bufferlen, writecount ;
908	sf_count_t	total = 0 ;
909	float		scale ;
910
911	scale = (psf->scale_int_float == 0) ? 1.0 : 1.0 / (8.0 * 0x10000000) ;
912	bufferlen = ARRAY_LEN (ubuf.fbuf) ;
913
914	while (len > 0)
915	{	if (len < bufferlen)
916			bufferlen = (int) len ;
917		i2f_array (ptr + total, ubuf.fbuf, bufferlen, scale) ;
918
919		if (psf->peak_info)
920			float32_peak_update (psf, ubuf.fbuf, bufferlen, total / psf->sf.channels) ;
921
922		f2bf_array (ubuf.fbuf, bufferlen) ;
923
924		if (psf->data_endswap == SF_TRUE)
925			endswap_int_array (ubuf.ibuf, bufferlen) ;
926
927		writecount = (int) psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
928		total += writecount ;
929		if (writecount < bufferlen)
930			break ;
931		len -= writecount ;
932		} ;
933
934	return total ;
935} /* replace_write_i2f */
936
937static sf_count_t
938replace_write_f	(SF_PRIVATE *psf, const float *ptr, sf_count_t len)
939{	BUF_UNION	ubuf ;
940	int			bufferlen, writecount ;
941	sf_count_t	total = 0 ;
942
943	/* FIX THIS */
944	if (psf->peak_info)
945		float32_peak_update (psf, ptr, len, 0) ;
946
947	bufferlen = ARRAY_LEN (ubuf.fbuf) ;
948
949	while (len > 0)
950	{	if (len < bufferlen)
951			bufferlen = (int) len ;
952
953		memcpy (ubuf.fbuf, ptr + total, bufferlen * sizeof (float)) ;
954
955		f2bf_array (ubuf.fbuf, bufferlen) ;
956
957		if (psf->data_endswap == SF_TRUE)
958			endswap_int_array (ubuf.ibuf, bufferlen) ;
959
960		writecount = (int) psf_fwrite (ubuf.fbuf, sizeof (float) , bufferlen, psf) ;
961		total += writecount ;
962		if (writecount < bufferlen)
963			break ;
964		len -= writecount ;
965		} ;
966
967	return total ;
968} /* replace_write_f */
969
970static sf_count_t
971replace_write_d2f	(SF_PRIVATE *psf, const double *ptr, sf_count_t len)
972{	BUF_UNION	ubuf ;
973	int			bufferlen, writecount ;
974	sf_count_t	total = 0 ;
975
976	bufferlen = ARRAY_LEN (ubuf.fbuf) ;
977
978	while (len > 0)
979	{	if (len < bufferlen)
980			bufferlen = (int) len ;
981		d2f_array (ptr + total, ubuf.fbuf, bufferlen) ;
982
983		if (psf->peak_info)
984			float32_peak_update (psf, ubuf.fbuf, bufferlen, total / psf->sf.channels) ;
985
986		f2bf_array (ubuf.fbuf, bufferlen) ;
987
988		if (psf->data_endswap == SF_TRUE)
989			endswap_int_array (ubuf.ibuf, bufferlen) ;
990
991		writecount = (int) psf_fwrite (ubuf.fbuf, sizeof (float), bufferlen, psf) ;
992		total += writecount ;
993		if (writecount < bufferlen)
994			break ;
995		len -= writecount ;
996		} ;
997
998	return total ;
999} /* replace_write_d2f */
1000
1001/*----------------------------------------------------------------------------------------------
1002*/
1003
1004static void
1005bf2f_array (float *buffer, int count)
1006{	for (int i = 0 ; i < count ; i++)
1007	{	buffer [i] = FLOAT32_READ ((unsigned char *) &buffer [i]) ;
1008		} ;
1009} /* bf2f_array */
1010
1011static void
1012f2bf_array (float *buffer, int count)
1013{	for (int i = 0 ; i < count ; i++)
1014	{	FLOAT32_WRITE (buffer [i], (unsigned char*) &buffer [i]) ;
1015		} ;
1016} /* f2bf_array */
1017
1018