Torque3D/Engine/lib/libsndfile/src/double64.c
marauder2k7 700bf32a2a Update minimum requirements and libs
This updates the minimum required cmake version and the libs that have updates for this.
Ogg updated to master as of 20052025
Libsndfile updated to master as of 20052025
Opus minimum cmake version changed
vorbis minimum cmake version changed
2025-05-20 10:09:42 +01:00

1063 lines
28 KiB
C

/*
** Copyright (C) 1999-2015 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "sfconfig.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <math.h>
#include "sndfile.h"
#include "sfendian.h"
#include "common.h"
#if CPU_IS_LITTLE_ENDIAN
#define DOUBLE64_READ double64_le_read
#define DOUBLE64_WRITE double64_le_write
#elif CPU_IS_BIG_ENDIAN
#define DOUBLE64_READ double64_be_read
#define DOUBLE64_WRITE double64_be_write
#endif
/* A 32 number which will not overflow when multiplied by sizeof (double). */
#define SENSIBLE_LEN (0x8000000)
/*--------------------------------------------------------------------------------------------
** Processor floating point capabilities. double64_get_capability () returns one of the
** latter three values.
*/
enum
{ DOUBLE_UNKNOWN = 0x00,
DOUBLE_CAN_RW_LE = 0x23,
DOUBLE_CAN_RW_BE = 0x34,
DOUBLE_BROKEN_LE = 0x45,
DOUBLE_BROKEN_BE = 0x56
} ;
/*--------------------------------------------------------------------------------------------
** Prototypes for private functions.
*/
static sf_count_t host_read_d2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
static sf_count_t host_read_d2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
static sf_count_t host_read_d2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
static sf_count_t host_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
static sf_count_t host_write_s2d (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
static sf_count_t host_write_i2d (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
static sf_count_t host_write_f2d (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
static sf_count_t host_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
static void double64_peak_update (SF_PRIVATE *psf, const double *buffer, int count, sf_count_t indx) ;
static int double64_get_capability (SF_PRIVATE *psf) ;
static sf_count_t replace_read_d2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
static sf_count_t replace_read_d2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
static sf_count_t replace_read_d2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
static sf_count_t replace_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
static sf_count_t replace_write_s2d (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
static sf_count_t replace_write_i2d (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
static sf_count_t replace_write_f2d (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
static sf_count_t replace_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
static void d2bd_read (double *buffer, int count) ;
static void bd2d_write (double *buffer, int count) ;
/*--------------------------------------------------------------------------------------------
** Exported functions.
*/
int
double64_init (SF_PRIVATE *psf)
{ static int double64_caps ;
if (psf->sf.channels < 1 || psf->sf.channels > SF_MAX_CHANNELS)
{ psf_log_printf (psf, "double64_init : internal error : channels = %d\n", psf->sf.channels) ;
return SFE_INTERNAL ;
} ;
double64_caps = double64_get_capability (psf) ;
psf->blockwidth = sizeof (double) * psf->sf.channels ;
if (psf->file.mode == SFM_READ || psf->file.mode == SFM_RDWR)
{ switch (psf->endian + double64_caps)
{ case (SF_ENDIAN_BIG + DOUBLE_CAN_RW_BE) :
psf->data_endswap = SF_FALSE ;
psf->read_short = host_read_d2s ;
psf->read_int = host_read_d2i ;
psf->read_float = host_read_d2f ;
psf->read_double = host_read_d ;
break ;
case (SF_ENDIAN_LITTLE + DOUBLE_CAN_RW_LE) :
psf->data_endswap = SF_FALSE ;
psf->read_short = host_read_d2s ;
psf->read_int = host_read_d2i ;
psf->read_float = host_read_d2f ;
psf->read_double = host_read_d ;
break ;
case (SF_ENDIAN_BIG + DOUBLE_CAN_RW_LE) :
psf->data_endswap = SF_TRUE ;
psf->read_short = host_read_d2s ;
psf->read_int = host_read_d2i ;
psf->read_float = host_read_d2f ;
psf->read_double = host_read_d ;
break ;
case (SF_ENDIAN_LITTLE + DOUBLE_CAN_RW_BE) :
psf->data_endswap = SF_TRUE ;
psf->read_short = host_read_d2s ;
psf->read_int = host_read_d2i ;
psf->read_float = host_read_d2f ;
psf->read_double = host_read_d ;
break ;
/* When the CPU is not IEEE compatible. */
case (SF_ENDIAN_BIG + DOUBLE_BROKEN_BE) :
psf->data_endswap = SF_FALSE ;
psf->read_short = replace_read_d2s ;
psf->read_int = replace_read_d2i ;
psf->read_float = replace_read_d2f ;
psf->read_double = replace_read_d ;
break ;
case (SF_ENDIAN_LITTLE + DOUBLE_BROKEN_LE) :
psf->data_endswap = SF_FALSE ;
psf->read_short = replace_read_d2s ;
psf->read_int = replace_read_d2i ;
psf->read_float = replace_read_d2f ;
psf->read_double = replace_read_d ;
break ;
case (SF_ENDIAN_BIG + DOUBLE_BROKEN_LE) :
psf->data_endswap = SF_TRUE ;
psf->read_short = replace_read_d2s ;
psf->read_int = replace_read_d2i ;
psf->read_float = replace_read_d2f ;
psf->read_double = replace_read_d ;
break ;
case (SF_ENDIAN_LITTLE + DOUBLE_BROKEN_BE) :
psf->data_endswap = SF_TRUE ;
psf->read_short = replace_read_d2s ;
psf->read_int = replace_read_d2i ;
psf->read_float = replace_read_d2f ;
psf->read_double = replace_read_d ;
break ;
default : break ;
} ;
} ;
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
{ switch (psf->endian + double64_caps)
{ case (SF_ENDIAN_LITTLE + DOUBLE_CAN_RW_LE) :
psf->data_endswap = SF_FALSE ;
psf->write_short = host_write_s2d ;
psf->write_int = host_write_i2d ;
psf->write_float = host_write_f2d ;
psf->write_double = host_write_d ;
break ;
case (SF_ENDIAN_BIG + DOUBLE_CAN_RW_BE) :
psf->data_endswap = SF_FALSE ;
psf->write_short = host_write_s2d ;
psf->write_int = host_write_i2d ;
psf->write_float = host_write_f2d ;
psf->write_double = host_write_d ;
break ;
case (SF_ENDIAN_BIG + DOUBLE_CAN_RW_LE) :
psf->data_endswap = SF_TRUE ;
psf->write_short = host_write_s2d ;
psf->write_int = host_write_i2d ;
psf->write_float = host_write_f2d ;
psf->write_double = host_write_d ;
break ;
case (SF_ENDIAN_LITTLE + DOUBLE_CAN_RW_BE) :
psf->data_endswap = SF_TRUE ;
psf->write_short = host_write_s2d ;
psf->write_int = host_write_i2d ;
psf->write_float = host_write_f2d ;
psf->write_double = host_write_d ;
break ;
/* When the CPU is not IEEE compatible. */
case (SF_ENDIAN_LITTLE + DOUBLE_BROKEN_LE) :
psf->data_endswap = SF_FALSE ;
psf->write_short = replace_write_s2d ;
psf->write_int = replace_write_i2d ;
psf->write_float = replace_write_f2d ;
psf->write_double = replace_write_d ;
break ;
case (SF_ENDIAN_BIG + DOUBLE_BROKEN_BE) :
psf->data_endswap = SF_FALSE ;
psf->write_short = replace_write_s2d ;
psf->write_int = replace_write_i2d ;
psf->write_float = replace_write_f2d ;
psf->write_double = replace_write_d ;
break ;
case (SF_ENDIAN_BIG + DOUBLE_BROKEN_LE) :
psf->data_endswap = SF_TRUE ;
psf->write_short = replace_write_s2d ;
psf->write_int = replace_write_i2d ;
psf->write_float = replace_write_f2d ;
psf->write_double = replace_write_d ;
break ;
case (SF_ENDIAN_LITTLE + DOUBLE_BROKEN_BE) :
psf->data_endswap = SF_TRUE ;
psf->write_short = replace_write_s2d ;
psf->write_int = replace_write_i2d ;
psf->write_float = replace_write_f2d ;
psf->write_double = replace_write_d ;
break ;
default : break ;
} ;
} ;
if (psf->filelength > psf->dataoffset)
{ psf->datalength = (psf->dataend > 0) ? psf->dataend - psf->dataoffset :
psf->filelength - psf->dataoffset ;
}
else
psf->datalength = 0 ;
psf->sf.frames = psf->datalength / psf->blockwidth ;
return 0 ;
} /* double64_init */
/*----------------------------------------------------------------------------
** From : http://www.hpcf.cam.ac.uk/fp_formats.html
**
** 64 bit double precision layout (big endian)
** Sign bit 0
** Exponent bits 1-11
** Mantissa bits 12-63
** Exponent Offset 1023
**
** double single
**
** +INF 7FF0000000000000 7F800000
** -INF FFF0000000000000 FF800000
** NaN 7FF0000000000001 7F800001
** to to
** 7FFFFFFFFFFFFFFF 7FFFFFFF
** and and
** FFF0000000000001 FF800001
** to to
** FFFFFFFFFFFFFFFF FFFFFFFF
** +OVER 7FEFFFFFFFFFFFFF 7F7FFFFF
** -OVER FFEFFFFFFFFFFFFF FF7FFFFF
** +UNDER 0010000000000000 00800000
** -UNDER 8010000000000000 80800000
*/
double
double64_be_read (const unsigned char *cptr)
{ int exponent, negative, upper, lower ;
double dvalue ;
negative = (cptr [0] & 0x80) ? 1 : 0 ;
exponent = ((cptr [0] & 0x7F) << 4) | ((cptr [1] >> 4) & 0xF) ;
/* Might not have a 64 bit long, so load the mantissa into a double. */
upper = (((cptr [1] & 0xF) << 24) | (cptr [2] << 16) | (cptr [3] << 8) | cptr [4]) ;
lower = (cptr [5] << 16) | (cptr [6] << 8) | cptr [7] ;
if (exponent == 0 && upper == 0 && lower == 0)
return 0.0 ;
dvalue = upper + lower / ((double) 0x1000000) ;
dvalue += 0x10000000 ;
exponent = exponent - 0x3FF ;
dvalue = dvalue / ((double) 0x10000000) ;
if (negative)
dvalue *= -1 ;
if (exponent > 0)
dvalue *= pow (2.0, exponent) ;
else if (exponent < 0)
dvalue /= pow (2.0, abs (exponent)) ;
return dvalue ;
} /* double64_be_read */
double
double64_le_read (const unsigned char *cptr)
{ int exponent, negative, upper, lower ;
double dvalue ;
negative = (cptr [7] & 0x80) ? 1 : 0 ;
exponent = ((cptr [7] & 0x7F) << 4) | ((cptr [6] >> 4) & 0xF) ;
/* Might not have a 64 bit long, so load the mantissa into a double. */
upper = ((cptr [6] & 0xF) << 24) | (cptr [5] << 16) | (cptr [4] << 8) | cptr [3] ;
lower = (cptr [2] << 16) | (cptr [1] << 8) | cptr [0] ;
if (exponent == 0 && upper == 0 && lower == 0)
return 0.0 ;
dvalue = upper + lower / ((double) 0x1000000) ;
dvalue += 0x10000000 ;
exponent = exponent - 0x3FF ;
dvalue = dvalue / ((double) 0x10000000) ;
if (negative)
dvalue *= -1 ;
if (exponent > 0)
dvalue *= pow (2.0, exponent) ;
else if (exponent < 0)
dvalue /= pow (2.0, abs (exponent)) ;
return dvalue ;
} /* double64_le_read */
void
double64_be_write (double in, unsigned char *out)
{ int exponent, mantissa ;
memset (out, 0, sizeof (double)) ;
if (fabs (in) < 1e-30)
return ;
if (in < 0.0)
{ in *= -1.0 ;
out [0] |= 0x80 ;
} ;
in = frexp (in, &exponent) ;
exponent += 1022 ;
out [0] |= (exponent >> 4) & 0x7F ;
out [1] |= (exponent << 4) & 0xF0 ;
in *= 0x20000000 ;
mantissa = psf_lrint (floor (in)) ;
out [1] |= (mantissa >> 24) & 0xF ;
out [2] = (mantissa >> 16) & 0xFF ;
out [3] = (mantissa >> 8) & 0xFF ;
out [4] = mantissa & 0xFF ;
in = fmod (in, 1.0) ;
in *= 0x1000000 ;
mantissa = psf_lrint (floor (in)) ;
out [5] = (mantissa >> 16) & 0xFF ;
out [6] = (mantissa >> 8) & 0xFF ;
out [7] = mantissa & 0xFF ;
return ;
} /* double64_be_write */
void
double64_le_write (double in, unsigned char *out)
{ int exponent, mantissa ;
memset (out, 0, sizeof (double)) ;
if (fabs (in) < 1e-30)
return ;
if (in < 0.0)
{ in *= -1.0 ;
out [7] |= 0x80 ;
} ;
in = frexp (in, &exponent) ;
exponent += 1022 ;
out [7] |= (exponent >> 4) & 0x7F ;
out [6] |= (exponent << 4) & 0xF0 ;
in *= 0x20000000 ;
mantissa = psf_lrint (floor (in)) ;
out [6] |= (mantissa >> 24) & 0xF ;
out [5] = (mantissa >> 16) & 0xFF ;
out [4] = (mantissa >> 8) & 0xFF ;
out [3] = mantissa & 0xFF ;
in = fmod (in, 1.0) ;
in *= 0x1000000 ;
mantissa = psf_lrint (floor (in)) ;
out [2] = (mantissa >> 16) & 0xFF ;
out [1] = (mantissa >> 8) & 0xFF ;
out [0] = mantissa & 0xFF ;
return ;
} /* double64_le_write */
/*==============================================================================================
** Private functions.
*/
static void
double64_peak_update (SF_PRIVATE *psf, const double *buffer, int count, sf_count_t indx)
{ int chan ;
int k, position ;
float fmaxval ;
for (chan = 0 ; chan < psf->sf.channels ; chan++)
{ fmaxval = fabs (buffer [chan]) ;
position = 0 ;
for (k = chan ; k < count ; k += psf->sf.channels)
if (fmaxval < fabs (buffer [k]))
{ fmaxval = fabs (buffer [k]) ;
position = k ;
} ;
if (fmaxval > psf->peak_info->peaks [chan].value)
{ psf->peak_info->peaks [chan].value = fmaxval ;
psf->peak_info->peaks [chan].position = psf->write_current + indx + (position / psf->sf.channels) ;
} ;
} ;
return ;
} /* double64_peak_update */
static int
double64_get_capability (SF_PRIVATE *psf)
{ union
{ double d ;
unsigned char c [8] ;
} data ;
data.d = 1.234567890123456789 ; /* Some arbitrary value. */
if (! psf->ieee_replace)
{ /* If this test is true ints and floats are compatible and little endian. */
if (data.c [0] == 0xfb && data.c [1] == 0x59 && data.c [2] == 0x8c && data.c [3] == 0x42 &&
data.c [4] == 0xca && data.c [5] == 0xc0 && data.c [6] == 0xf3 && data.c [7] == 0x3f)
return DOUBLE_CAN_RW_LE ;
/* If this test is true ints and floats are compatible and big endian. */
if (data.c [0] == 0x3f && data.c [1] == 0xf3 && data.c [2] == 0xc0 && data.c [3] == 0xca &&
data.c [4] == 0x42 && data.c [5] == 0x8c && data.c [6] == 0x59 && data.c [7] == 0xfb)
return DOUBLE_CAN_RW_BE ;
} ;
/* Doubles are broken. Don't expect reading or writing to be fast. */
psf_log_printf (psf, "Using IEEE replacement code for double.\n") ;
return (CPU_IS_LITTLE_ENDIAN) ? DOUBLE_BROKEN_LE : DOUBLE_BROKEN_BE ;
} /* double64_get_capability */
/*=======================================================================================
*/
static void
d2s_array (const double *src, int count, short *dest, double scale)
{ for (int i = 0 ; i < count ; i++)
{ dest [i] = psf_lrint (scale * src [i]) ;
} ;
} /* d2s_array */
static void
d2s_clip_array (const double *src, int count, short *dest, double scale)
{ for (int i = 0 ; i < count ; i++)
{ double tmp = scale * src [i] ;
if (tmp > 32767.0)
dest [i] = SHRT_MAX ;
else if (tmp < -32768.0)
dest [i] = SHRT_MIN ;
else
dest [i] = psf_lrint (tmp) ;
} ;
} /* d2s_clip_array */
static void
d2i_array (const double *src, int count, int *dest, double scale)
{ for (int i = 0 ; i < count ; i++)
{ dest [i] = psf_lrint (scale * src [i]) ;
} ;
} /* d2i_array */
static void
d2i_clip_array (const double *src, int count, int *dest, double scale)
{ for (int i = 0 ; i < count ; i++)
{ float tmp = scale * src [i] ;
if (tmp > (1.0 * INT_MAX))
dest [i] = INT_MAX ;
else if (tmp < (-1.0 * INT_MAX))
dest [i] = INT_MIN ;
else
dest [i] = psf_lrint (tmp) ;
} ;
} /* d2i_clip_array */
static inline void
d2f_array (const double *src, int count, float *dest)
{ for (int i = 0 ; i < count ; i++)
{ dest [i] = src [i] ;
} ;
} /* d2f_array */
static inline void
s2d_array (const short *src, double *dest, int count, double scale)
{ for (int i = 0 ; i < count ; i++)
{ dest [i] = scale * src [i] ;
} ;
} /* s2d_array */
static inline void
i2d_array (const int *src, double *dest, int count, double scale)
{ for (int i = 0 ; i < count ; i++)
{ dest [i] = scale * src [i] ;
} ;
} /* i2d_array */
static inline void
f2d_array (const float *src, double *dest, int count)
{ for (int i = 0 ; i < count ; i++)
{ dest [i] = src [i] ;
} ;
} /* f2d_array */
/*----------------------------------------------------------------------------------------------
*/
static sf_count_t
host_read_d2s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
{ BUF_UNION ubuf ;
void (*convert) (const double *, int, short *, double) ;
int bufferlen, readcount ;
sf_count_t total = 0 ;
double scale ;
convert = (psf->add_clipping) ? d2s_clip_array : d2s_array ;
bufferlen = ARRAY_LEN (ubuf.dbuf) ;
scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFF / psf->float_max ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
if (psf->data_endswap == SF_TRUE)
endswap_double_array (ubuf.dbuf, readcount) ;
convert (ubuf.dbuf, readcount, ptr + total, scale) ;
total += readcount ;
len -= readcount ;
if (readcount < bufferlen)
break ;
} ;
return total ;
} /* host_read_d2s */
static sf_count_t
host_read_d2i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
{ BUF_UNION ubuf ;
void (*convert) (const double *, int, int *, double) ;
int bufferlen, readcount ;
sf_count_t total = 0 ;
double scale ;
convert = (psf->add_clipping) ? d2i_clip_array : d2i_array ;
bufferlen = ARRAY_LEN (ubuf.dbuf) ;
scale = (psf->float_int_mult == 0) ? 1.0 : 2147483648.0f / psf->float_max ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
if (psf->data_endswap == SF_TRUE)
endswap_double_array (ubuf.dbuf, bufferlen) ;
convert (ubuf.dbuf, readcount, ptr + total, scale) ;
total += readcount ;
len -= readcount ;
if (readcount < bufferlen)
break ;
} ;
return total ;
} /* host_read_d2i */
static sf_count_t
host_read_d2f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
{ BUF_UNION ubuf ;
int bufferlen, readcount ;
sf_count_t total = 0 ;
bufferlen = ARRAY_LEN (ubuf.dbuf) ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
if (psf->data_endswap == SF_TRUE)
endswap_double_array (ubuf.dbuf, readcount) ;
d2f_array (ubuf.dbuf, readcount, ptr + total) ;
total += readcount ;
len -= readcount ;
if (readcount < bufferlen)
break ;
} ;
return total ;
} /* host_read_d2f */
static sf_count_t
host_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
{ int bufferlen ;
sf_count_t readcount, total = 0 ;
readcount = psf_fread (ptr, sizeof (double), len, psf) ;
if (psf->data_endswap != SF_TRUE)
return readcount ;
/* If the read length was sensible, endswap output in one go. */
if (readcount < SENSIBLE_LEN)
{ endswap_double_array (ptr, readcount) ;
return readcount ;
} ;
bufferlen = SENSIBLE_LEN ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
endswap_double_array (ptr + total, bufferlen) ;
total += bufferlen ;
len -= bufferlen ;
} ;
return total ;
} /* host_read_d */
static sf_count_t
host_write_s2d (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
{ BUF_UNION ubuf ;
int bufferlen, writecount ;
sf_count_t total = 0 ;
double scale ;
scale = (psf->scale_int_float == 0) ? 1.0 : 1.0 / 0x8000 ;
bufferlen = ARRAY_LEN (ubuf.dbuf) ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
s2d_array (ptr + total, ubuf.dbuf, bufferlen, scale) ;
if (psf->peak_info)
double64_peak_update (psf, ubuf.dbuf, bufferlen, total / psf->sf.channels) ;
if (psf->data_endswap == SF_TRUE)
endswap_double_array (ubuf.dbuf, bufferlen) ;
writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
total += writecount ;
if (writecount < bufferlen)
break ;
len -= writecount ;
} ;
return total ;
} /* host_write_s2d */
static sf_count_t
host_write_i2d (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
{ BUF_UNION ubuf ;
int bufferlen, writecount ;
sf_count_t total = 0 ;
double scale ;
scale = (psf->scale_int_float == 0) ? 1.0 : 1.0 / (8.0 * 0x10000000) ;
bufferlen = ARRAY_LEN (ubuf.dbuf) ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
i2d_array (ptr + total, ubuf.dbuf, bufferlen, scale) ;
if (psf->peak_info)
double64_peak_update (psf, ubuf.dbuf, bufferlen, total / psf->sf.channels) ;
if (psf->data_endswap == SF_TRUE)
endswap_double_array (ubuf.dbuf, bufferlen) ;
writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
total += writecount ;
if (writecount < bufferlen)
break ;
len -= writecount ;
} ;
return total ;
} /* host_write_i2d */
static sf_count_t
host_write_f2d (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
{ BUF_UNION ubuf ;
int bufferlen, writecount ;
sf_count_t total = 0 ;
bufferlen = ARRAY_LEN (ubuf.dbuf) ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
f2d_array (ptr + total, ubuf.dbuf, bufferlen) ;
if (psf->peak_info)
double64_peak_update (psf, ubuf.dbuf, bufferlen, total / psf->sf.channels) ;
if (psf->data_endswap == SF_TRUE)
endswap_double_array (ubuf.dbuf, bufferlen) ;
writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
total += writecount ;
if (writecount < bufferlen)
break ;
len -= writecount ;
} ;
return total ;
} /* host_write_f2d */
static sf_count_t
host_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
{ BUF_UNION ubuf ;
int bufferlen, writecount ;
sf_count_t total = 0 ;
if (psf->peak_info)
double64_peak_update (psf, ptr, len, 0) ;
if (psf->data_endswap != SF_TRUE)
return psf_fwrite (ptr, sizeof (double), len, psf) ;
bufferlen = ARRAY_LEN (ubuf.dbuf) ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
endswap_double_copy (ubuf.dbuf, ptr + total, bufferlen) ;
writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
total += writecount ;
if (writecount < bufferlen)
break ;
len -= writecount ;
} ;
return total ;
} /* host_write_d */
/*=======================================================================================
*/
static sf_count_t
replace_read_d2s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
{ BUF_UNION ubuf ;
int bufferlen, readcount ;
sf_count_t total = 0 ;
double scale ;
bufferlen = ARRAY_LEN (ubuf.dbuf) ;
scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFF / psf->float_max ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
if (psf->data_endswap == SF_TRUE)
endswap_double_array (ubuf.dbuf, bufferlen) ;
d2bd_read (ubuf.dbuf, bufferlen) ;
d2s_array (ubuf.dbuf, readcount, ptr + total, scale) ;
total += readcount ;
if (readcount < bufferlen)
break ;
len -= readcount ;
} ;
return total ;
} /* replace_read_d2s */
static sf_count_t
replace_read_d2i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
{ BUF_UNION ubuf ;
int bufferlen, readcount ;
sf_count_t total = 0 ;
double scale ;
bufferlen = ARRAY_LEN (ubuf.dbuf) ;
scale = (psf->float_int_mult == 0) ? 1.0 : 2147483648.0f / psf->float_max ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
if (psf->data_endswap == SF_TRUE)
endswap_double_array (ubuf.dbuf, bufferlen) ;
d2bd_read (ubuf.dbuf, bufferlen) ;
d2i_array (ubuf.dbuf, readcount, ptr + total, scale) ;
total += readcount ;
if (readcount < bufferlen)
break ;
len -= readcount ;
} ;
return total ;
} /* replace_read_d2i */
static sf_count_t
replace_read_d2f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
{ BUF_UNION ubuf ;
int bufferlen, readcount ;
sf_count_t total = 0 ;
bufferlen = ARRAY_LEN (ubuf.dbuf) ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
if (psf->data_endswap == SF_TRUE)
endswap_double_array (ubuf.dbuf, bufferlen) ;
d2bd_read (ubuf.dbuf, bufferlen) ;
memcpy (ptr + total, ubuf.dbuf, bufferlen * sizeof (double)) ;
total += readcount ;
if (readcount < bufferlen)
break ;
len -= readcount ;
} ;
return total ;
} /* replace_read_d2f */
static sf_count_t
replace_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
{ BUF_UNION ubuf ;
int bufferlen, readcount ;
sf_count_t total = 0 ;
/* FIXME : This is probably nowhere near optimal. */
bufferlen = ARRAY_LEN (ubuf.dbuf) ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
readcount = (int) psf_fread (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
if (psf->data_endswap == SF_TRUE)
endswap_double_array (ubuf.dbuf, readcount) ;
d2bd_read (ubuf.dbuf, readcount) ;
memcpy (ptr + total, ubuf.dbuf, readcount * sizeof (double)) ;
total += readcount ;
if (readcount < bufferlen)
break ;
len -= readcount ;
} ;
return total ;
} /* replace_read_d */
static sf_count_t
replace_write_s2d (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
{ BUF_UNION ubuf ;
int bufferlen, writecount ;
sf_count_t total = 0 ;
double scale ;
scale = (psf->scale_int_float == 0) ? 1.0 : 1.0 / 0x8000 ;
bufferlen = ARRAY_LEN (ubuf.dbuf) ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
s2d_array (ptr + total, ubuf.dbuf, bufferlen, scale) ;
if (psf->peak_info)
double64_peak_update (psf, ubuf.dbuf, bufferlen, total / psf->sf.channels) ;
bd2d_write (ubuf.dbuf, bufferlen) ;
if (psf->data_endswap == SF_TRUE)
endswap_double_array (ubuf.dbuf, bufferlen) ;
writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
total += writecount ;
if (writecount < bufferlen)
break ;
len -= writecount ;
} ;
return total ;
} /* replace_write_s2d */
static sf_count_t
replace_write_i2d (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
{ BUF_UNION ubuf ;
int bufferlen, writecount ;
sf_count_t total = 0 ;
double scale ;
scale = (psf->scale_int_float == 0) ? 1.0 : 1.0 / (8.0 * 0x10000000) ;
bufferlen = ARRAY_LEN (ubuf.dbuf) ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
i2d_array (ptr + total, ubuf.dbuf, bufferlen, scale) ;
if (psf->peak_info)
double64_peak_update (psf, ubuf.dbuf, bufferlen, total / psf->sf.channels) ;
bd2d_write (ubuf.dbuf, bufferlen) ;
if (psf->data_endswap == SF_TRUE)
endswap_double_array (ubuf.dbuf, bufferlen) ;
writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
total += writecount ;
if (writecount < bufferlen)
break ;
len -= writecount ;
} ;
return total ;
} /* replace_write_i2d */
static sf_count_t
replace_write_f2d (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
{ BUF_UNION ubuf ;
int bufferlen, writecount ;
sf_count_t total = 0 ;
bufferlen = ARRAY_LEN (ubuf.dbuf) ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
f2d_array (ptr + total, ubuf.dbuf, bufferlen) ;
bd2d_write (ubuf.dbuf, bufferlen) ;
if (psf->data_endswap == SF_TRUE)
endswap_double_array (ubuf.dbuf, bufferlen) ;
writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
total += writecount ;
if (writecount < bufferlen)
break ;
len -= writecount ;
} ;
return total ;
} /* replace_write_f2d */
static sf_count_t
replace_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
{ BUF_UNION ubuf ;
int bufferlen, writecount ;
sf_count_t total = 0 ;
/* FIXME : This is probably nowhere near optimal. */
if (psf->peak_info)
double64_peak_update (psf, ptr, len, 0) ;
bufferlen = ARRAY_LEN (ubuf.dbuf) ;
while (len > 0)
{ if (len < bufferlen)
bufferlen = (int) len ;
memcpy (ubuf.dbuf, ptr + total, bufferlen * sizeof (double)) ;
bd2d_write (ubuf.dbuf, bufferlen) ;
if (psf->data_endswap == SF_TRUE)
endswap_double_array (ubuf.dbuf, bufferlen) ;
writecount = (int) psf_fwrite (ubuf.dbuf, sizeof (double), bufferlen, psf) ;
total += writecount ;
if (writecount < bufferlen)
break ;
len -= writecount ;
} ;
return total ;
} /* replace_write_d */
/*----------------------------------------------------------------------------------------------
*/
static void
d2bd_read (double *buffer, int count)
{ for (int i = 0 ; i < count ; i++)
{ buffer [i] = DOUBLE64_READ ((unsigned char *) &buffer [i]) ;
} ;
} /* d2bd_read */
static void
bd2d_write (double *buffer, int count)
{ for (int i = 0 ; i < count ; i++)
{ DOUBLE64_WRITE (buffer [i], (unsigned char*) &buffer [i]) ;
} ;
} /* bd2d_write */