diff --git a/src/double64.c b/src/double64.c index 6513f7d6..f5d95b78 100644 --- a/src/double64.c +++ b/src/double64.c @@ -1,5 +1,5 @@ /* -** Copyright (C) 1999-2005 Erik de Castro Lopo +** Copyright (C) 1999-2006 Erik de Castro Lopo ** ** 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 @@ -21,6 +21,7 @@ #include #include #include +#include #include "sndfile.h" #include "sfendian.h" @@ -478,20 +479,48 @@ double64_get_capability (SF_PRIVATE *psf) /*======================================================================================= */ -static inline void +static void d2s_array (const double *src, int count, short *dest, double scale) { while (--count >= 0) { dest [count] = lrint (scale * src [count]) ; } ; } /* d2s_array */ -static inline void +static void +d2s_clip_array (const double *src, int count, short *dest, double scale) +{ while (--count >= 0) + { double tmp = scale * src [count] ; + + if (CPU_CLIPS_POSITIVE == 0 && tmp > 32767.0) + dest [count] = SHRT_MAX ; + else if (CPU_CLIPS_NEGATIVE == 0 && tmp < 32768.0) + dest [count] = SHRT_MIN ; + else + dest [count] = lrint (tmp) ; + } ; +} /* d2s_clip_array */ + +static void d2i_array (const double *src, int count, int *dest, double scale) { while (--count >= 0) { dest [count] = lrint (scale * src [count]) ; } ; } /* d2i_array */ +static void +d2i_clip_array (const double *src, int count, int *dest, double scale) +{ while (--count >= 0) + { float tmp = scale * src [count] ; + + if (CPU_CLIPS_POSITIVE == 0 && tmp > (1.0 * INT_MAX)) + dest [count] = INT_MAX ; + else if (CPU_CLIPS_NEGATIVE == 0 && tmp < (-1.0 * INT_MAX)) + dest [count] = INT_MIN ; + else + dest [count] = lrint (tmp) ; + } ; +} /* d2i_clip_array */ + static inline void d2f_array (const double *src, int count, float *dest) { while (--count >= 0) @@ -525,10 +554,12 @@ f2d_array (const float *src, double *dest, int count) static sf_count_t host_read_d2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) -{ int bufferlen, readcount ; +{ 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 (psf->u.dbuf) ; scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFF / psf->float_max ; @@ -540,7 +571,7 @@ host_read_d2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) if (psf->float_endswap == SF_TRUE) endswap_double_array (psf->u.dbuf, readcount) ; - d2s_array (psf->u.dbuf, readcount, ptr + total, scale) ; + convert (psf->u.dbuf, readcount, ptr + total, scale) ; total += readcount ; len -= readcount ; if (readcount < bufferlen) @@ -552,9 +583,12 @@ 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) -{ int bufferlen, readcount ; +{ 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 (psf->u.dbuf) ; scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFFFFFF / psf->float_max ; @@ -566,7 +600,7 @@ host_read_d2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) if (psf->float_endswap == SF_TRUE) endswap_double_array (psf->u.dbuf, bufferlen) ; - d2i_array (psf->u.dbuf, readcount, ptr + total, scale) ; + convert (psf->u.dbuf, readcount, ptr + total, scale) ; total += readcount ; len -= readcount ; if (readcount < bufferlen) diff --git a/src/float32.c b/src/float32.c index b376e60f..b3e87253 100644 --- a/src/float32.c +++ b/src/float32.c @@ -1,5 +1,5 @@ /* -** Copyright (C) 1999-2005 Erik de Castro Lopo +** Copyright (C) 1999-2006 Erik de Castro Lopo ** ** 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 @@ -21,6 +21,7 @@ #include #include #include +#include #include "sndfile.h" #include "sfendian.h" @@ -428,13 +429,28 @@ float32_get_capability (SF_PRIVATE *psf) /*======================================================================================= */ -static inline void +static void f2s_array (const float *src, int count, short *dest, float scale) -{ while (--count >= 0) +{ + while (--count >= 0) { dest [count] = lrintf (scale * src [count]) ; } ; } /* f2s_array */ +static void +f2s_clip_array (const float *src, int count, short *dest, float scale) +{ while (--count >= 0) + { float tmp = scale * src [count] ; + + if (CPU_CLIPS_POSITIVE == 0 && tmp > 32767.0) + dest [count] = SHRT_MAX ; + else if (CPU_CLIPS_NEGATIVE == 0 && tmp < 32768.0) + dest [count] = SHRT_MIN ; + else + dest [count] = lrintf (tmp) ; + } ; +} /* f2s_clip_array */ + static inline void f2i_array (const float *src, int count, int *dest, float scale) { while (--count >= 0) @@ -442,6 +458,20 @@ f2i_array (const float *src, int count, int *dest, float scale) } ; } /* f2i_array */ +static inline void +f2i_clip_array (const float *src, int count, int *dest, float scale) +{ while (--count >= 0) + { float tmp = scale * src [count] ; + + if (CPU_CLIPS_POSITIVE == 0 && tmp > (1.0 * INT_MAX)) + dest [count] = INT_MAX ; + else if (CPU_CLIPS_NEGATIVE == 0 && tmp < (-1.0 * INT_MAX)) + dest [count] = INT_MIN ; + else + dest [count] = lrintf (tmp) ; + } ; +} /* f2i_clip_array */ + static inline void f2d_array (const float *src, int count, double *dest) { while (--count >= 0) @@ -476,10 +506,12 @@ d2f_array (const double *src, float *dest, int count) static sf_count_t host_read_f2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) -{ int bufferlen, readcount ; +{ void (*convert) (const float *, int, short *, float) ; + int bufferlen, readcount ; sf_count_t total = 0 ; float scale ; + convert = (psf->add_clipping) ? f2s_clip_array : f2s_array ; bufferlen = ARRAY_LEN (psf->u.fbuf) ; scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFF / psf->float_max ; @@ -504,10 +536,12 @@ host_read_f2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) static sf_count_t host_read_f2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) -{ int bufferlen, readcount ; +{ void (*convert) (const float *, int, int *, float) ; + int bufferlen, readcount ; sf_count_t total = 0 ; float scale ; + convert = (psf->add_clipping) ? f2i_clip_array : f2i_array ; bufferlen = ARRAY_LEN (psf->u.fbuf) ; scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFFFFFF / psf->float_max ; @@ -519,7 +553,7 @@ host_read_f2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) if (psf->float_endswap == SF_TRUE) endswap_int_array (psf->u.ibuf, bufferlen) ; - f2i_array (psf->u.fbuf, readcount, ptr + total, scale) ; + convert (psf->u.fbuf, readcount, ptr + total, scale) ; total += readcount ; if (readcount < bufferlen) break ;