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