PageRenderTime 80ms CodeModel.GetById 15ms app.highlight 57ms RepoModel.GetById 1ms app.codeStats 1ms

/project/jni/sndfile/src/double64.c

https://github.com/aichunyu/FFPlayer
C | 1043 lines | 739 code | 231 blank | 73 comment | 189 complexity | 69f0320336875b94132888e6bb8e639d MD5 | raw file
   1/*
   2** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
   3**
   4** This program is free software; you can redistribute it and/or modify
   5** it under the terms of the GNU Lesser General Public License as published by
   6** the Free Software Foundation; either version 2.1 of the License, or
   7** (at your option) any later version.
   8**
   9** This program is distributed in the hope that it will be useful,
  10** but WITHOUT ANY WARRANTY; without even the implied warranty of
  11** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12** GNU Lesser General Public License for more details.
  13**
  14** You should have received a copy of the GNU Lesser General Public License
  15** along with this program; if not, write to the Free Software
  16** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17*/
  18
  19#include	"sfconfig.h"
  20
  21#include	<stdio.h>
  22#include	<stdlib.h>
  23#include	<string.h>
  24#include	<limits.h>
  25#include	<math.h>
  26
  27#include	"sndfile.h"
  28#include	"sfendian.h"
  29#include	"common.h"
  30
  31#if CPU_IS_LITTLE_ENDIAN
  32	#define DOUBLE64_READ	double64_le_read
  33	#define DOUBLE64_WRITE	double64_le_write
  34#elif CPU_IS_BIG_ENDIAN
  35	#define DOUBLE64_READ	double64_be_read
  36	#define DOUBLE64_WRITE	double64_be_write
  37#endif
  38
  39/* A 32 number which will not overflow when multiplied by sizeof (double). */
  40#define SENSIBLE_LEN	(0x8000000)
  41
  42/*--------------------------------------------------------------------------------------------
  43**	Processor floating point capabilities. double64_get_capability () returns one of the
  44**	latter three values.
  45*/
  46
  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