pulling trunk
[ardour.git] / libs / libsndfile / src / common.c
1 /*
2 ** Copyright (C) 1999-2006 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        <stdarg.h>
20 #include        <string.h>
21 #include        <ctype.h>
22 #include        <math.h>
23 #include        <time.h>
24
25 #include        "sndfile.h"
26 #include        "sfendian.h"
27 #include        "common.h"
28
29 /*-----------------------------------------------------------------------------------------------
30 ** psf_log_printf allows libsndfile internal functions to print to an internal logbuffer which
31 ** can later be displayed.
32 ** The format specifiers are as for printf but without the field width and other modifiers.
33 ** Printing is performed to the logbuffer char array of the SF_PRIVATE struct.
34 ** Printing is done in such a way as to guarantee that the log never overflows the end of the
35 ** logbuffer array.
36 */
37
38 static inline void
39 log_putchar (SF_PRIVATE *psf, char ch)
40 {       if (psf->logindex < SIGNED_SIZEOF (psf->logbuffer) - 1)
41         {       psf->logbuffer [psf->logindex++] = ch ;
42                 psf->logbuffer [psf->logindex] = 0 ;
43                 } ;
44         return ;
45 } /* log_putchar */
46
47 void
48 psf_log_printf (SF_PRIVATE *psf, const char *format, ...)
49 {       va_list                 ap ;
50         unsigned int    u ;
51         int                             d, tens, shift, width, width_specifier, left_align ;
52         char                    c, *strptr, istr [5], lead_char, sign_char ;
53
54         va_start (ap, format) ;
55
56         while ((c = *format++))
57         {       if (c != '%')
58                 {       log_putchar (psf, c) ;
59                         continue ;
60                         } ;
61
62                 if (format [0] == '%') /* Handle %% */
63                 {       log_putchar (psf, '%') ;
64                         format ++ ;
65                         continue ;
66                         } ;
67
68                 sign_char = 0 ;
69                 left_align = SF_FALSE ;
70                 while (1)
71                 {       switch (format [0])
72                         {       case ' ' :
73                                 case '+' :
74                                         sign_char = format [0] ;
75                                         format ++ ;
76                                         continue ;
77
78                                 case '-' :
79                                         left_align = SF_TRUE ;
80                                         format ++ ;
81                                         continue ;
82
83                                 default : break ;
84                                 } ;
85
86                         break ;
87                         } ;
88
89                 if (format [0] == 0)
90                         break ;
91
92                 lead_char = ' ' ;
93                 if (format [0] == '0')
94                         lead_char = '0' ;
95
96                 width_specifier = 0 ;
97                 while ((c = *format++) && isdigit (c))
98                         width_specifier = width_specifier * 10 + (c - '0') ;
99
100                 switch (c)
101                 {       case 0 : /* NULL character. */
102                                         va_end (ap) ;
103                                         return ;
104
105                         case 's': /* string */
106                                         strptr = va_arg (ap, char *) ;
107                                         if (strptr == NULL)
108                                                 break ;
109                                         width_specifier -= strlen (strptr) ;
110                                         if (left_align == SF_FALSE)
111                                                 while (width_specifier -- > 0)
112                                                         log_putchar (psf, ' ') ;
113                                         while (*strptr)
114                                                 log_putchar (psf, *strptr++) ;
115                                         while (width_specifier -- > 0)
116                                                 log_putchar (psf, ' ') ;
117                                         break ;
118
119                         case 'd': /* int */
120                                         d = va_arg (ap, int) ;
121
122                                         if (d < 0)
123                                         {       d = -d ;
124                                                 sign_char = '-' ;
125                                                 if (lead_char != '0' && left_align == SF_FALSE)
126                                                         width_specifier -- ;
127                                                 } ;
128
129                                         tens = 1 ;
130                                         width = 1 ;
131                                         while (d / tens >= 10)
132                                         {       tens *= 10 ;
133                                                 width ++ ;
134                                                 } ;
135
136                                         width_specifier -= width ;
137
138                                         if (sign_char == ' ')
139                                         {       log_putchar (psf, ' ') ;
140                                                 width_specifier -- ;
141                                                 } ;
142
143                                         if (left_align == SF_FALSE && lead_char != '0')
144                                         {       if (sign_char == '+')
145                                                         width_specifier -- ;
146
147                                                 while (width_specifier -- > 0)
148                                                         log_putchar (psf, lead_char) ;
149                                                 } ;
150
151                                         if (sign_char == '+' || sign_char == '-')
152                                         {       log_putchar (psf, sign_char) ;
153                                                 width_specifier -- ;
154                                                 } ;
155
156                                         if (left_align == SF_FALSE)
157                                                 while (width_specifier -- > 0)
158                                                         log_putchar (psf, lead_char) ;
159
160                                         while (tens > 0)
161                                         {       log_putchar (psf, '0' + d / tens) ;
162                                                 d %= tens ;
163                                                 tens /= 10 ;
164                                                 } ;
165
166                                         while (width_specifier -- > 0)
167                                                 log_putchar (psf, lead_char) ;
168                                         break ;
169
170                         case 'D': /* sf_count_t */
171                                         {       sf_count_t              D, Tens ;
172
173                                                 D = va_arg (ap, sf_count_t) ;
174
175                                                 if (D == 0)
176                                                 {       while (-- width_specifier > 0)
177                                                                 log_putchar (psf, lead_char) ;
178                                                         log_putchar (psf, '0') ;
179                                                         break ;
180                                                         }
181                                                 if (D < 0)
182                                                 {       log_putchar (psf, '-') ;
183                                                         D = -D ;
184                                                         } ;
185                                                 Tens = 1 ;
186                                                 width = 1 ;
187                                                 while (D / Tens >= 10)
188                                                 {       Tens *= 10 ;
189                                                         width ++ ;
190                                                         } ;
191
192                                                 while (width_specifier > width)
193                                                 {       log_putchar (psf, lead_char) ;
194                                                         width_specifier-- ;
195                                                         } ;
196
197                                                 while (Tens > 0)
198                                                 {       log_putchar (psf, '0' + D / Tens) ;
199                                                         D %= Tens ;
200                                                         Tens /= 10 ;
201                                                         } ;
202                                                 } ;
203                                         break ;
204
205                         case 'u': /* unsigned int */
206                                         u = va_arg (ap, unsigned int) ;
207
208                                         tens = 1 ;
209                                         width = 1 ;
210                                         while (u / tens >= 10)
211                                         {       tens *= 10 ;
212                                                 width ++ ;
213                                                 } ;
214
215                                         width_specifier -= width ;
216
217                                         if (sign_char == ' ')
218                                         {       log_putchar (psf, ' ') ;
219                                                 width_specifier -- ;
220                                                 } ;
221
222                                         if (left_align == SF_FALSE && lead_char != '0')
223                                         {       if (sign_char == '+')
224                                                         width_specifier -- ;
225
226                                                 while (width_specifier -- > 0)
227                                                         log_putchar (psf, lead_char) ;
228                                                 } ;
229
230                                         if (sign_char == '+' || sign_char == '-')
231                                         {       log_putchar (psf, sign_char) ;
232                                                 width_specifier -- ;
233                                                 } ;
234
235                                         if (left_align == SF_FALSE)
236                                                 while (width_specifier -- > 0)
237                                                         log_putchar (psf, lead_char) ;
238
239                                         while (tens > 0)
240                                         {       log_putchar (psf, '0' + u / tens) ;
241                                                 u %= tens ;
242                                                 tens /= 10 ;
243                                                 } ;
244
245                                         while (width_specifier -- > 0)
246                                                 log_putchar (psf, lead_char) ;
247                                         break ;
248
249                         case 'c': /* char */
250                                         c = va_arg (ap, int) & 0xFF ;
251                                         log_putchar (psf, c) ;
252                                         break ;
253
254                         case 'x': /* hex */
255                         case 'X': /* hex */
256                                         d = va_arg (ap, int) ;
257
258                                         if (d == 0)
259                                         {       while (--width_specifier > 0)
260                                                         log_putchar (psf, lead_char) ;
261                                                 log_putchar (psf, '0') ;
262                                                 break ;
263                                                 } ;
264                                         shift = 28 ;
265                                         width = (width_specifier < 8) ? 8 : width_specifier ;
266                                         while (! ((0xF << shift) & d))
267                                         {       shift -= 4 ;
268                                                 width -- ;
269                                                 } ;
270
271                                         while (width > 0 && width_specifier > width)
272                                         {       log_putchar (psf, lead_char) ;
273                                                 width_specifier-- ;
274                                                 } ;
275
276                                         while (shift >= 0)
277                                         {       c = (d >> shift) & 0xF ;
278                                                 log_putchar (psf, (c > 9) ? c + 'A' - 10 : c + '0') ;
279                                                 shift -= 4 ;
280                                                 } ;
281                                         break ;
282
283                         case 'M': /* int2str */
284                                         d = va_arg (ap, int) ;
285                                         if (CPU_IS_LITTLE_ENDIAN)
286                                         {       istr [0] = d & 0xFF ;
287                                                 istr [1] = (d >> 8) & 0xFF ;
288                                                 istr [2] = (d >> 16) & 0xFF ;
289                                                 istr [3] = (d >> 24) & 0xFF ;
290                                                 }
291                                         else
292                                         {       istr [3] = d & 0xFF ;
293                                                 istr [2] = (d >> 8) & 0xFF ;
294                                                 istr [1] = (d >> 16) & 0xFF ;
295                                                 istr [0] = (d >> 24) & 0xFF ;
296                                                 } ;
297                                         istr [4] = 0 ;
298                                         strptr = istr ;
299                                         while (*strptr)
300                                         {       c = *strptr++ ;
301                                                 log_putchar (psf, c) ;
302                                                 } ;
303                                         break ;
304
305                         default :
306                                         log_putchar (psf, '*') ;
307                                         log_putchar (psf, c) ;
308                                         log_putchar (psf, '*') ;
309                                         break ;
310                         } /* switch */
311                 } /* while */
312
313         va_end (ap) ;
314         return ;
315 } /* psf_log_printf */
316
317 #ifndef PSF_LOG_PRINTF_ONLY
318 /*-----------------------------------------------------------------------------------------------
319 **  ASCII header printf functions.
320 **  Some formats (ie NIST) use ascii text in their headers.
321 **  Format specifiers are the same as the standard printf specifiers (uses vsnprintf).
322 **  If this generates a compile error on any system, the author should be notified
323 **  so an alternative vsnprintf can be provided.
324 */
325
326 void
327 psf_asciiheader_printf (SF_PRIVATE *psf, const char *format, ...)
328 {       va_list argptr ;
329         int             maxlen ;
330         char    *start ;
331
332         maxlen = strlen ((char*) psf->header) ;
333         start   = ((char*) psf->header) + maxlen ;
334         maxlen  = sizeof (psf->header) - maxlen ;
335
336         va_start (argptr, format) ;
337         LSF_VSNPRINTF (start, maxlen, format, argptr) ;
338         va_end (argptr) ;
339
340         /* Make sure the string is properly terminated. */
341         start [maxlen - 1] = 0 ;
342
343         psf->headindex = strlen ((char*) psf->header) ;
344
345         return ;
346 } /* psf_asciiheader_printf */
347
348 /*-----------------------------------------------------------------------------------------------
349 **  Binary header writing functions. Returns number of bytes written.
350 **
351 **  Format specifiers for psf_binheader_writef are as follows
352 **              m       - marker - four bytes - no endian manipulation
353 **
354 **              e   - all following numerical values will be little endian
355 **              E   - all following numerical values will be big endian
356 **
357 **              t   - all following O types will be truncated to 4 bytes
358 **              T   - switch off truncation of all following O types
359 **
360 **              1       - single byte value
361 **              2       - two byte value
362 **              3       - three byte value
363 **              4       - four byte value
364 **              8       - eight byte value (sometimes written as 4 bytes)
365 **
366 **              s   - string preceded by a four byte length
367 **              S   - string including null terminator
368 **              f       - floating point data
369 **              d       - double precision floating point data
370 **              h       - 16 binary bytes value
371 **
372 **              b       - binary data (see below)
373 **              z   - zero bytes (ses below)
374 **              j       - jump forwards or backwards
375 **
376 **      To write a word followed by an int (both little endian) use:
377 **              psf_binheader_writef ("e24", wordval, longval) ;
378 **
379 **      To write binary data use:
380 **              psf_binheader_writef ("b", &bindata, sizeof (bindata)) ;
381 **
382 **      To write N zero bytes use:
383 **                      NOTE: due to platform issues (ie x86-64) you should cast the
384 **                      argument to size_t or ensure the variable type is size_t.
385 **              psf_binheader_writef ("z", N) ;
386 */
387
388 /* These macros may seem a bit messy but do prevent problems with processors which
389 ** seg. fault when asked to write an int or short to a non-int/short aligned address.
390 */
391
392 static inline void
393 header_put_byte (SF_PRIVATE *psf, char x)
394 {       if (psf->headindex < SIGNED_SIZEOF (psf->header) - 1)
395                 psf->header [psf->headindex++] = x ;
396 } /* header_put_byte */
397
398 #if (CPU_IS_BIG_ENDIAN == 1)
399 static inline void
400 header_put_marker (SF_PRIVATE *psf, int x)
401 {       if (psf->headindex < SIGNED_SIZEOF (psf->header) - 4)
402         {       psf->header [psf->headindex++] = (x >> 24) ;
403                 psf->header [psf->headindex++] = (x >> 16) ;
404                 psf->header [psf->headindex++] = (x >> 8) ;
405                 psf->header [psf->headindex++] = x ;
406                 } ;
407 } /* header_put_marker */
408
409 #elif (CPU_IS_LITTLE_ENDIAN == 1)
410 static inline void
411 header_put_marker (SF_PRIVATE *psf, int x)
412 {       if (psf->headindex < SIGNED_SIZEOF (psf->header) - 4)
413         {       psf->header [psf->headindex++] = x ;
414                 psf->header [psf->headindex++] = (x >> 8) ;
415                 psf->header [psf->headindex++] = (x >> 16) ;
416                 psf->header [psf->headindex++] = (x >> 24) ;
417                 } ;
418 } /* header_put_marker */
419
420 #else
421 #       error "Cannot determine endian-ness of processor."
422 #endif
423
424
425 static inline void
426 header_put_be_short (SF_PRIVATE *psf, int x)
427 {       if (psf->headindex < SIGNED_SIZEOF (psf->header) - 2)
428         {       psf->header [psf->headindex++] = (x >> 8) ;
429                 psf->header [psf->headindex++] = x ;
430                 } ;
431 } /* header_put_be_short */
432
433 static inline void
434 header_put_le_short (SF_PRIVATE *psf, int x)
435 {       if (psf->headindex < SIGNED_SIZEOF (psf->header) - 2)
436         {       psf->header [psf->headindex++] = x ;
437                 psf->header [psf->headindex++] = (x >> 8) ;
438                 } ;
439 } /* header_put_le_short */
440
441 static inline void
442 header_put_be_3byte (SF_PRIVATE *psf, int x)
443 {       if (psf->headindex < SIGNED_SIZEOF (psf->header) - 3)
444         {       psf->header [psf->headindex++] = (x >> 16) ;
445                 psf->header [psf->headindex++] = (x >> 8) ;
446                 psf->header [psf->headindex++] = x ;
447                 } ;
448 } /* header_put_be_3byte */
449
450 static inline void
451 header_put_le_3byte (SF_PRIVATE *psf, int x)
452 {       if (psf->headindex < SIGNED_SIZEOF (psf->header) - 3)
453         {       psf->header [psf->headindex++] = x ;
454                 psf->header [psf->headindex++] = (x >> 8) ;
455                 psf->header [psf->headindex++] = (x >> 16) ;
456                 } ;
457 } /* header_put_le_3byte */
458
459 static inline void
460 header_put_be_int (SF_PRIVATE *psf, int x)
461 {       if (psf->headindex < SIGNED_SIZEOF (psf->header) - 4)
462         {       psf->header [psf->headindex++] = (x >> 24) ;
463                 psf->header [psf->headindex++] = (x >> 16) ;
464                 psf->header [psf->headindex++] = (x >> 8) ;
465                 psf->header [psf->headindex++] = x ;
466                 } ;
467 } /* header_put_be_int */
468
469 static inline void
470 header_put_le_int (SF_PRIVATE *psf, int x)
471 {       if (psf->headindex < SIGNED_SIZEOF (psf->header) - 4)
472         {       psf->header [psf->headindex++] = x ;
473                 psf->header [psf->headindex++] = (x >> 8) ;
474                 psf->header [psf->headindex++] = (x >> 16) ;
475                 psf->header [psf->headindex++] = (x >> 24) ;
476                 } ;
477 } /* header_put_le_int */
478
479 #if (SIZEOF_SF_COUNT_T == 4)
480
481 static inline void
482 header_put_be_8byte (SF_PRIVATE *psf, sf_count_t x)
483 {       if (psf->headindex < SIGNED_SIZEOF (psf->header) - 8)
484         {       psf->header [psf->headindex++] = 0 ;
485                 psf->header [psf->headindex++] = 0 ;
486                 psf->header [psf->headindex++] = 0 ;
487                 psf->header [psf->headindex++] = 0 ;
488                 psf->header [psf->headindex++] = (x >> 24) ;
489                 psf->header [psf->headindex++] = (x >> 16) ;
490                 psf->header [psf->headindex++] = (x >> 8) ;
491                 psf->header [psf->headindex++] = x ;
492                 } ;
493 } /* header_put_be_8byte */
494
495 static inline void
496 header_put_le_8byte (SF_PRIVATE *psf, sf_count_t x)
497 {       if (psf->headindex < SIGNED_SIZEOF (psf->header) - 8)
498         {       psf->header [psf->headindex++] = x ;
499                 psf->header [psf->headindex++] = (x >> 8) ;
500                 psf->header [psf->headindex++] = (x >> 16) ;
501                 psf->header [psf->headindex++] = (x >> 24) ;
502                 psf->header [psf->headindex++] = 0 ;
503                 psf->header [psf->headindex++] = 0 ;
504                 psf->header [psf->headindex++] = 0 ;
505                 psf->header [psf->headindex++] = 0 ;
506                 } ;
507 } /* header_put_le_8byte */
508
509 #elif (SIZEOF_SF_COUNT_T == 8)
510
511 static inline void
512 header_put_be_8byte (SF_PRIVATE *psf, sf_count_t x)
513 {       if (psf->headindex < SIGNED_SIZEOF (psf->header) - 8)
514         {       psf->header [psf->headindex++] = (x >> 56) ;
515                 psf->header [psf->headindex++] = (x >> 48) ;
516                 psf->header [psf->headindex++] = (x >> 40) ;
517                 psf->header [psf->headindex++] = (x >> 32) ;
518                 psf->header [psf->headindex++] = (x >> 24) ;
519                 psf->header [psf->headindex++] = (x >> 16) ;
520                 psf->header [psf->headindex++] = (x >> 8) ;
521                 psf->header [psf->headindex++] = x ;
522                 } ;
523 } /* header_put_be_8byte */
524
525 static inline void
526 header_put_le_8byte (SF_PRIVATE *psf, sf_count_t x)
527 {       if (psf->headindex < SIGNED_SIZEOF (psf->header) - 8)
528         {       psf->header [psf->headindex++] = x ;
529                 psf->header [psf->headindex++] = (x >> 8) ;
530                 psf->header [psf->headindex++] = (x >> 16) ;
531                 psf->header [psf->headindex++] = (x >> 24) ;
532                 psf->header [psf->headindex++] = (x >> 32) ;
533                 psf->header [psf->headindex++] = (x >> 40) ;
534                 psf->header [psf->headindex++] = (x >> 48) ;
535                 psf->header [psf->headindex++] = (x >> 56) ;
536                 } ;
537 } /* header_put_le_8byte */
538
539 #else
540 #error "SIZEOF_SF_COUNT_T is not defined."
541 #endif
542
543 int
544 psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...)
545 {       va_list argptr ;
546         sf_count_t              countdata ;
547         unsigned long   longdata ;
548         unsigned int    data ;
549         float                   floatdata ;
550         double                  doubledata ;
551         void                    *bindata ;
552         size_t                  size ;
553         char                    c, *strptr ;
554         int                             count = 0, trunc_8to4 ;
555
556         trunc_8to4 = SF_FALSE ;
557
558         va_start (argptr, format) ;
559
560         while ((c = *format++))
561         {       switch (c)
562                 {       case ' ' : /* Do nothing. Just used to space out format string. */
563                                         break ;
564
565                         case 'e' : /* All conversions are now from LE to host. */
566                                         psf->rwf_endian = SF_ENDIAN_LITTLE ;
567                                         break ;
568
569                         case 'E' : /* All conversions are now from BE to host. */
570                                         psf->rwf_endian = SF_ENDIAN_BIG ;
571                                         break ;
572
573                         case 't' : /* All 8 byte values now get written as 4 bytes. */
574                                         trunc_8to4 = SF_TRUE ;
575                                         break ;
576
577                         case 'T' : /* All 8 byte values now get written as 8 bytes. */
578                                         trunc_8to4 = SF_FALSE ;
579                                         break ;
580
581                         case 'm' :
582                                         data = va_arg (argptr, unsigned int) ;
583                                         header_put_marker (psf, data) ;
584                                         count += 4 ;
585                                         break ;
586
587                         case '1' :
588                                         data = va_arg (argptr, unsigned int) ;
589                                         header_put_byte (psf, data) ;
590                                         count += 1 ;
591                                         break ;
592
593                         case '2' :
594                                         data = va_arg (argptr, unsigned int) ;
595                                         if (psf->rwf_endian == SF_ENDIAN_BIG)
596                                         {       header_put_be_short (psf, data) ;
597                                                 }
598                                         else
599                                         {       header_put_le_short (psf, data) ;
600                                                 } ;
601                                         count += 2 ;
602                                         break ;
603
604                         case '3' : /* tribyte */
605                                         data = va_arg (argptr, unsigned int) ;
606                                         if (psf->rwf_endian == SF_ENDIAN_BIG)
607                                         {       header_put_be_3byte (psf, data) ;
608                                                 }
609                                         else
610                                         {       header_put_le_3byte (psf, data) ;
611                                                 } ;
612                                         count += 3 ;
613                                         break ;
614
615                         case '4' :
616                                         data = va_arg (argptr, unsigned int) ;
617                                         if (psf->rwf_endian == SF_ENDIAN_BIG)
618                                         {       header_put_be_int (psf, data) ;
619                                                 }
620                                         else
621                                         {       header_put_le_int (psf, data) ;
622                                                 } ;
623                                         count += 4 ;
624                                         break ;
625
626                         case '8' :
627                                         countdata = va_arg (argptr, sf_count_t) ;
628                                         if (psf->rwf_endian == SF_ENDIAN_BIG && trunc_8to4 == SF_FALSE)
629                                         {       header_put_be_8byte (psf, countdata) ;
630                                                 count += 8 ;
631                                                 }
632                                         else if (psf->rwf_endian == SF_ENDIAN_LITTLE && trunc_8to4 == SF_FALSE)
633                                         {       header_put_le_8byte (psf, countdata) ;
634                                                 count += 8 ;
635                                                 }
636                                         else if (psf->rwf_endian == SF_ENDIAN_BIG && trunc_8to4 == SF_TRUE)
637                                         {       longdata = countdata & 0xFFFFFFFF ;
638                                                 header_put_be_int (psf, longdata) ;
639                                                 count += 4 ;
640                                                 }
641                                         else if (psf->rwf_endian == SF_ENDIAN_LITTLE && trunc_8to4 == SF_TRUE)
642                                         {       longdata = countdata & 0xFFFFFFFF ;
643                                                 header_put_le_int (psf, longdata) ;
644                                                 count += 4 ;
645                                                 }
646                                         break ;
647
648                         case 'f' :
649                                         /* Floats are passed as doubles. Is this always true? */
650                                         floatdata = (float) va_arg (argptr, double) ;
651                                         if (psf->rwf_endian == SF_ENDIAN_BIG)
652                                                 float32_be_write (floatdata, psf->header + psf->headindex) ;
653                                         else
654                                                 float32_le_write (floatdata, psf->header + psf->headindex) ;
655                                         psf->headindex += 4 ;
656                                         count += 4 ;
657                                         break ;
658
659                         case 'd' :
660                                         doubledata = va_arg (argptr, double) ;
661                                         if (psf->rwf_endian == SF_ENDIAN_BIG)
662                                                 double64_be_write (doubledata, psf->header + psf->headindex) ;
663                                         else
664                                                 double64_le_write (doubledata, psf->header + psf->headindex) ;
665                                         psf->headindex += 8 ;
666                                         count += 8 ;
667                                         break ;
668
669                         case 's' :
670                                         /* Write a C string (guaranteed to have a zero terminator). */
671                                         strptr = va_arg (argptr, char *) ;
672                                         size = strlen (strptr) + 1 ;
673                                         size += (size & 1) ;
674                                         if (psf->rwf_endian == SF_ENDIAN_BIG)
675                                                 header_put_be_int (psf, size) ;
676                                         else
677                                                 header_put_le_int (psf, size) ;
678                                         memcpy (&(psf->header [psf->headindex]), strptr, size) ;
679                                         psf->headindex += size ;
680                                         psf->header [psf->headindex - 1] = 0 ;
681                                         count += 4 + size ;
682                                         break ;
683
684                         case 'S' :
685                                         /*
686                                         **      Write an AIFF style string (no zero terminator but possibly
687                                         **      an extra pad byte if the string length is odd).
688                                         */
689                                         strptr = va_arg (argptr, char *) ;
690                                         size = strlen (strptr) ;
691                                         if (psf->rwf_endian == SF_ENDIAN_BIG)
692                                                 header_put_be_int (psf, size) ;
693                                         else
694                                                 header_put_le_int (psf, size) ;
695                                         memcpy (&(psf->header [psf->headindex]), strptr, size + 1) ;
696                                         size += (size & 1) ;
697                                         psf->headindex += size ;
698                                         psf->header [psf->headindex] = 0 ;
699                                         count += 4 + size ;
700                                         break ;
701
702                         case 'b' :
703                                         bindata = va_arg (argptr, void *) ;
704                                         size    = va_arg (argptr, size_t) ;
705                                         memcpy (&(psf->header [psf->headindex]), bindata, size) ;
706                                         psf->headindex += size ;
707                                         count += size ;
708                                         break ;
709
710                         case 'z' :
711                                         size = va_arg (argptr, size_t) ;
712                                         count += size ;
713                                         while (size)
714                                         {       psf->header [psf->headindex] = 0 ;
715                                                 psf->headindex ++ ;
716                                                 size -- ;
717                                                 } ;
718                                         break ;
719
720                         case 'h' :
721                                         bindata = va_arg (argptr, void *) ;
722                                         memcpy (&(psf->header [psf->headindex]), bindata, 16) ;
723                                         psf->headindex += 16 ;
724                                         count += 16 ;
725                                         break ;
726
727                         case 'j' :
728                                         size = va_arg (argptr, size_t) ;
729                                         psf->headindex += size ;
730                                         count = size ;
731                                         break ;
732
733                         default :
734                                 psf_log_printf (psf, "*** Invalid format specifier `%c'\n", c) ;
735                                 psf->error = SFE_INTERNAL ;
736                                 break ;
737                         } ;
738                 } ;
739
740         va_end (argptr) ;
741         return count ;
742 } /* psf_binheader_writef */
743
744 /*-----------------------------------------------------------------------------------------------
745 **  Binary header reading functions. Returns number of bytes read.
746 **
747 **      Format specifiers are the same as for header write function above with the following
748 **      additions:
749 **
750 **              p   - jump a given number of position from start of file.
751 **
752 **      If format is NULL, psf_binheader_readf returns the current offset.
753 */
754
755 #if (CPU_IS_BIG_ENDIAN == 1)
756 #define GET_MARKER(ptr) (       ((ptr) [0] << 24)       | ((ptr) [1] << 16) |   \
757                                                         ((ptr) [2] << 8)        | ((ptr) [3]) )
758
759 #elif (CPU_IS_LITTLE_ENDIAN == 1)
760 #define GET_MARKER(ptr) (       ((ptr) [0])                     | ((ptr) [1] << 8) |    \
761                                                         ((ptr) [2] << 16)       | ((ptr) [3] << 24) )
762
763 #else
764 #       error "Cannot determine endian-ness of processor."
765 #endif
766
767 #define GET_LE_SHORT(ptr)       ( ((ptr) [1] << 8) | ((ptr) [0]) )
768 #define GET_BE_SHORT(ptr)       ( ((ptr) [0] << 8) | ((ptr) [1]) )
769
770 #define GET_LE_3BYTE(ptr)       (       ((ptr) [2] << 16) | ((ptr) [1] << 8) | ((ptr) [0]) )
771 #define GET_BE_3BYTE(ptr)       (       ((ptr) [0] << 16) | ((ptr) [1] << 8) | ((ptr) [2]) )
772
773 #define GET_LE_INT(ptr)         (       ((ptr) [3] << 24)       | ((ptr) [2] << 16) |   \
774                                                                 ((ptr) [1] << 8)        | ((ptr) [0]) )
775
776 #define GET_BE_INT(ptr)         (       ((ptr) [0] << 24)       | ((ptr) [1] << 16) |   \
777                                                                 ((ptr) [2] << 8)        | ((ptr) [3]) )
778
779 #if (SIZEOF_LONG == 4)
780 #define GET_LE_8BYTE(ptr)       (       ((ptr) [3] << 24)       | ((ptr) [2] << 16) |   \
781                                                                 ((ptr) [1] << 8)        | ((ptr) [0]) )
782
783 #define GET_BE_8BYTE(ptr)       (       ((ptr) [4] << 24)       | ((ptr) [5] << 16) |   \
784                                                                 ((ptr) [6] << 8)        | ((ptr) [7]) )
785 #else
786 #define GET_LE_8BYTE(ptr)       (       (((ptr) [7] * 1L) << 56) | (((ptr) [6] * 1L) << 48) |   \
787                                                                 (((ptr) [5] * 1L) << 40) | (((ptr) [4] * 1L) << 32) |   \
788                                                                 (((ptr) [3] * 1L) << 24) | (((ptr) [2] * 1L) << 16) |   \
789                                                                 (((ptr) [1] * 1L) << 8 ) | ((ptr) [0]))
790
791 #define GET_BE_8BYTE(ptr)       (       (((ptr) [0] * 1L) << 56) | (((ptr) [1] * 1L) << 48) |   \
792                                                                 (((ptr) [2] * 1L) << 40) | (((ptr) [3] * 1L) << 32) |   \
793                                                                 (((ptr) [4] * 1L) << 24) | (((ptr) [5] * 1L) << 16) |   \
794                                                                 (((ptr) [6] * 1L) << 8 ) | ((ptr) [7]))
795
796 #endif
797
798 static int
799 header_read (SF_PRIVATE *psf, void *ptr, int bytes)
800 {       int count = 0 ;
801
802         if (psf->headindex >= SIGNED_SIZEOF (psf->header))
803         {       memset (ptr, 0, SIGNED_SIZEOF (psf->header) - psf->headindex) ;
804
805                 /* This is the best that we can do. */
806                 psf_fseek (psf, bytes, SEEK_CUR) ;
807                 return bytes ;
808                 } ;
809
810         if (psf->headindex + bytes > SIGNED_SIZEOF (psf->header))
811         {       int most ;
812
813                 most = SIGNED_SIZEOF (psf->header) - psf->headindex ;
814                 psf_fread (psf->header + psf->headend, 1, most, psf) ;
815                 memset (ptr + most, 0, bytes - most) ;
816
817                 psf_fseek (psf, bytes - most, SEEK_CUR) ;
818                 return bytes ;
819                 } ;
820
821         if (psf->headindex + bytes > psf->headend)
822         {       count = psf_fread (psf->header + psf->headend, 1, bytes - (psf->headend - psf->headindex), psf) ;
823                 if (count != bytes - (int) (psf->headend - psf->headindex))
824                 {       psf_log_printf (psf, "Error : psf_fread returned short count.\n") ;
825                         return 0 ;
826                         } ;
827                 psf->headend += count ;
828                 } ;
829
830         memcpy (ptr, psf->header + psf->headindex, bytes) ;
831         psf->headindex += bytes ;
832
833         return bytes ;
834 } /* header_read */
835
836 static void
837 header_seek (SF_PRIVATE *psf, sf_count_t position, int whence)
838 {
839
840         switch (whence)
841         {       case SEEK_SET :
842                         if (position > SIGNED_SIZEOF (psf->header))
843                         {       /* Too much header to cache so just seek instead. */
844                                 psf_fseek (psf, position, whence) ;
845                                 return ;
846                                 } ;
847                         if (position > psf->headend)
848                                 psf->headend += psf_fread (psf->header + psf->headend, 1, position - psf->headend, psf) ;
849                         psf->headindex = position ;
850                         break ;
851
852                 case SEEK_CUR :
853                         if (psf->headindex + position < 0)
854                                 break ;
855
856                         if (psf->headindex >= SIGNED_SIZEOF (psf->header))
857                         {       psf_fseek (psf, position, whence) ;
858                                 return ;
859                                 } ;
860
861                         if (psf->headindex + position <= psf->headend)
862                         {       psf->headindex += position ;
863                                 break ;
864                                 } ;
865
866                         if (psf->headindex + position > SIGNED_SIZEOF (psf->header))
867                         {       /* Need to jump this without caching it. */
868                                 psf->headindex = psf->headend ;
869                                 psf_fseek (psf, position, SEEK_CUR) ;
870                                 break ;
871                                 } ;
872
873                         psf->headend += psf_fread (psf->header + psf->headend, 1, position - (psf->headend - psf->headindex), psf) ;
874                         psf->headindex = psf->headend ;
875                         break ;
876
877                 case SEEK_END :
878                 default :
879                         psf_log_printf (psf, "Bad whence param in header_seek().\n") ;
880                         break ;
881                 } ;
882
883         return ;
884 } /* header_seek */
885
886 static int
887 header_gets (SF_PRIVATE *psf, char *ptr, int bufsize)
888 {
889         int             k ;
890
891         for (k = 0 ; k < bufsize - 1 ; k++)
892         {       if (psf->headindex < psf->headend)
893                 {       ptr [k] = psf->header [psf->headindex] ;
894                         psf->headindex ++ ;
895                         }
896                 else
897                 {       psf->headend += psf_fread (psf->header + psf->headend, 1, 1, psf) ;
898                         ptr [k] = psf->header [psf->headindex] ;
899                         psf->headindex = psf->headend ;
900                         } ;
901
902                 if (ptr [k] == '\n')
903                         break ;
904                 } ;
905
906         ptr [k] = 0 ;
907
908         return k ;
909 } /* header_gets */
910
911 int
912 psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...)
913 {       va_list                 argptr ;
914         sf_count_t              *countptr, countdata ;
915         unsigned char   *ucptr, sixteen_bytes [16] ;
916         unsigned int    *intptr, intdata ;
917         unsigned short  *shortptr ;
918         char                    *charptr ;
919         float                   *floatptr ;
920         double                  *doubleptr ;
921         char                    c ;
922         int                             byte_count = 0, count ;
923
924         if (! format)
925                 return psf_ftell (psf) ;
926
927         va_start (argptr, format) ;
928
929         while ((c = *format++))
930         {       switch (c)
931                 {       case 'e' : /* All conversions are now from LE to host. */
932                                         psf->rwf_endian = SF_ENDIAN_LITTLE ;
933                                         break ;
934
935                         case 'E' : /* All conversions are now from BE to host. */
936                                         psf->rwf_endian = SF_ENDIAN_BIG ;
937                                         break ;
938
939                         case 'm' :
940                                         intptr = va_arg (argptr, unsigned int*) ;
941                                         ucptr = (unsigned char*) intptr ;
942                                         byte_count += header_read (psf, ucptr, sizeof (int)) ;
943                                         *intptr = GET_MARKER (ucptr) ;
944                                         break ;
945
946                         case 'h' :
947                                         intptr = va_arg (argptr, unsigned int*) ;
948                                         ucptr = (unsigned char*) intptr ;
949                                         byte_count += header_read (psf, sixteen_bytes, sizeof (sixteen_bytes)) ;
950                                         {       int k ;
951                                                 intdata = 0 ;
952                                                 for (k = 0 ; k < 16 ; k++)
953                                                         intdata ^= sixteen_bytes [k] << k ;
954                                                 }
955                                         *intptr = intdata ;
956                                         break ;
957
958                         case '1' :
959                                         charptr = va_arg (argptr, char*) ;
960                                         *charptr = 0 ;
961                                         byte_count += header_read (psf, charptr, sizeof (char)) ;
962                                         break ;
963
964                         case '2' :
965                                         shortptr = va_arg (argptr, unsigned short*) ;
966                                         *shortptr = 0 ;
967                                         ucptr = (unsigned char*) shortptr ;
968                                         byte_count += header_read (psf, ucptr, sizeof (short)) ;
969                                         if (psf->rwf_endian == SF_ENDIAN_BIG)
970                                                 *shortptr = GET_BE_SHORT (ucptr) ;
971                                         else
972                                                 *shortptr = GET_LE_SHORT (ucptr) ;
973                                         break ;
974
975                         case '3' :
976                                         intptr = va_arg (argptr, unsigned int*) ;
977                                         *intptr = 0 ;
978                                         byte_count += header_read (psf, sixteen_bytes, 3) ;
979                                         if (psf->rwf_endian == SF_ENDIAN_BIG)
980                                                 *intptr = GET_BE_3BYTE (sixteen_bytes) ;
981                                         else
982                                                 *intptr = GET_LE_3BYTE (sixteen_bytes) ;
983                                         break ;
984
985                         case '4' :
986                                         intptr = va_arg (argptr, unsigned int*) ;
987                                         *intptr = 0 ;
988                                         ucptr = (unsigned char*) intptr ;
989                                         byte_count += header_read (psf, ucptr, sizeof (int)) ;
990                                         if (psf->rwf_endian == SF_ENDIAN_BIG)
991                                                 *intptr = GET_BE_INT (ucptr) ;
992                                         else
993                                                 *intptr = GET_LE_INT (ucptr) ;
994                                         break ;
995
996                         case '8' :
997                                         countptr = va_arg (argptr, sf_count_t *) ;
998                                         *countptr = 0 ;
999                                         byte_count += header_read (psf, sixteen_bytes, 8) ;
1000                                         if (psf->rwf_endian == SF_ENDIAN_BIG)
1001                                                 countdata = GET_BE_8BYTE (sixteen_bytes) ;
1002                                         else
1003                                                 countdata = GET_LE_8BYTE (sixteen_bytes) ;
1004                                         *countptr = countdata ;
1005                                         break ;
1006
1007                         case 'f' : /* Float conversion */
1008                                         floatptr = va_arg (argptr, float *) ;
1009                                         *floatptr = 0.0 ;
1010                                         byte_count += header_read (psf, floatptr, sizeof (float)) ;
1011                                         if (psf->rwf_endian == SF_ENDIAN_BIG)
1012                                                 *floatptr = float32_be_read ((unsigned char*) floatptr) ;
1013                                         else
1014                                                 *floatptr = float32_le_read ((unsigned char*) floatptr) ;
1015                                         break ;
1016
1017                         case 'd' : /* double conversion */
1018                                         doubleptr = va_arg (argptr, double *) ;
1019                                         *doubleptr = 0.0 ;
1020                                         byte_count += header_read (psf, doubleptr, sizeof (double)) ;
1021                                         if (psf->rwf_endian == SF_ENDIAN_BIG)
1022                                                 *doubleptr = double64_be_read ((unsigned char*) doubleptr) ;
1023                                         else
1024                                                 *doubleptr = double64_le_read ((unsigned char*) doubleptr) ;
1025                                         break ;
1026
1027                         case 's' :
1028                                         psf_log_printf (psf, "Format conversion 's' not implemented yet.\n") ;
1029                                         /*
1030                                         strptr = va_arg (argptr, char *) ;
1031                                         size   = strlen (strptr) + 1 ;
1032                                         size  += (size & 1) ;
1033                                         longdata = H2LE_INT (size) ;
1034                                         get_int (psf, longdata) ;
1035                                         memcpy (&(psf->header [psf->headindex]), strptr, size) ;
1036                                         psf->headindex += size ;
1037                                         */
1038                                         break ;
1039
1040                         case 'b' :
1041                                         charptr = va_arg (argptr, char*) ;
1042                                         count = va_arg (argptr, int) ;
1043                                         if (count > 0)
1044                                                 byte_count += header_read (psf, charptr, count) ;
1045                                         break ;
1046
1047                         case 'G' :
1048                                         charptr = va_arg (argptr, char*) ;
1049                                         count = va_arg (argptr, int) ;
1050                                         if (count > 0)
1051                                                 byte_count += header_gets (psf, charptr, count) ;
1052                                         break ;
1053
1054                         case 'z' :
1055                                         psf_log_printf (psf, "Format conversion 'z' not implemented yet.\n") ;
1056                                         /*
1057                                         size    = va_arg (argptr, size_t) ;
1058                                         while (size)
1059                                         {       psf->header [psf->headindex] = 0 ;
1060                                                 psf->headindex ++ ;
1061                                                 size -- ;
1062                                                 } ;
1063                                         */
1064                                         break ;
1065
1066                         case 'p' :
1067                                         /* Get the seek position first. */
1068                                         count = va_arg (argptr, int) ;
1069                                         header_seek (psf, count, SEEK_SET) ;
1070                                         byte_count = count ;
1071                                         break ;
1072
1073                         case 'j' :
1074                                         /* Get the seek position first. */
1075                                         count = va_arg (argptr, int) ;
1076                                         header_seek (psf, count, SEEK_CUR) ;
1077                                         byte_count += count ;
1078                                         break ;
1079
1080                         default :
1081                                 psf_log_printf (psf, "*** Invalid format specifier `%c'\n", c) ;
1082                                 psf->error = SFE_INTERNAL ;
1083                                 break ;
1084                         } ;
1085                 } ;
1086
1087         va_end (argptr) ;
1088
1089         return byte_count ;
1090 } /* psf_binheader_readf */
1091
1092 /*-----------------------------------------------------------------------------------------------
1093 */
1094
1095 sf_count_t
1096 psf_default_seek (SF_PRIVATE *psf, int mode, sf_count_t samples_from_start)
1097 {       sf_count_t position, retval ;
1098
1099         if (! (psf->blockwidth && psf->dataoffset >= 0))
1100         {       psf->error = SFE_BAD_SEEK ;
1101                 return  PSF_SEEK_ERROR ;
1102                 } ;
1103
1104         if (! psf->sf.seekable)
1105         {       psf->error = SFE_NOT_SEEKABLE ;
1106                 return  PSF_SEEK_ERROR ;
1107                 } ;
1108
1109         position = psf->dataoffset + psf->blockwidth * samples_from_start ;
1110
1111         if ((retval = psf_fseek (psf, position, SEEK_SET)) != position)
1112         {       psf->error = SFE_SEEK_FAILED ;
1113                 return PSF_SEEK_ERROR ;
1114                 } ;
1115
1116         mode = mode ;
1117
1118         return samples_from_start ;
1119 } /* psf_default_seek */
1120
1121 /*-----------------------------------------------------------------------------------------------
1122 */
1123
1124 void
1125 psf_hexdump (void *ptr, int len)
1126 {       char    ascii [17], *data ;
1127         int             k, m ;
1128
1129         if ((data = ptr) == NULL)
1130                 return ;
1131         if (len <= 0)
1132                 return ;
1133
1134         puts ("") ;
1135         for (k = 0 ; k < len ; k += 16)
1136         {       memset (ascii, ' ', sizeof (ascii)) ;
1137
1138                 printf ("%08X: ", k) ;
1139                 for (m = 0 ; m < 16 && k + m < len ; m++)
1140                 {       printf (m == 8 ? " %02X " : "%02X ", data [k + m] & 0xFF) ;
1141                         ascii [m] = isprint (data [k + m]) ? data [k + m] : '.' ;
1142                         } ;
1143
1144                 if (m <= 8) printf (" ") ;
1145                 for ( ; m < 16 ; m++) printf ("   ") ;
1146
1147                 ascii [16] = 0 ;
1148                 printf (" %s\n", ascii) ;
1149                 } ;
1150
1151         puts ("") ;
1152 } /* psf_hexdump */
1153
1154 void
1155 psf_log_SF_INFO (SF_PRIVATE *psf)
1156 {       psf_log_printf (psf, "---------------------------------\n") ;
1157
1158         psf_log_printf (psf, " Sample rate :   %d\n", psf->sf.samplerate) ;
1159         psf_log_printf (psf, " Frames      :   %D\n", psf->sf.frames) ;
1160         psf_log_printf (psf, " Channels    :   %d\n", psf->sf.channels) ;
1161
1162         psf_log_printf (psf, " Format      :   0x%X\n", psf->sf.format) ;
1163         psf_log_printf (psf, " Sections    :   %d\n", psf->sf.sections) ;
1164         psf_log_printf (psf, " Seekable    :   %s\n", psf->sf.seekable ? "TRUE" : "FALSE") ;
1165
1166         psf_log_printf (psf, "---------------------------------\n") ;
1167 } /* psf_dump_SFINFO */
1168
1169 /*========================================================================================
1170 */
1171
1172 SF_INSTRUMENT *
1173 psf_instrument_alloc (void)
1174 {       SF_INSTRUMENT *instr ;
1175
1176         instr = calloc (1, sizeof (SF_INSTRUMENT)) ;
1177
1178         if (instr == NULL)
1179                 return NULL ;
1180
1181         /* Set non-zero default values. */
1182         instr->basenote = -1 ;
1183         instr->velocity_lo = -1 ;
1184         instr->velocity_hi = -1 ;
1185         instr->key_lo = -1 ;
1186         instr->key_hi = -1 ;
1187
1188         return instr ;
1189 } /* psf_instrument_alloc */
1190
1191 void*
1192 psf_memset (void *s, int c, sf_count_t len)
1193 {       char    *ptr ;
1194         int     setcount ;
1195
1196         ptr = (char *) s ;
1197
1198         while (len > 0)
1199         {       setcount = (len > 0x10000000) ? 0x10000000 : (int) len ;
1200
1201                 memset (ptr, c, setcount) ;
1202
1203                 ptr += setcount ;
1204                 len -= setcount ;
1205                 } ;
1206
1207         return s ;
1208 } /* psf_memset */
1209
1210 void psf_get_date_str (char *str, int maxlen)
1211 {       time_t          current ;
1212         struct tm       timedata, *tmptr ;
1213
1214         time (&current) ;
1215
1216 #if defined (HAVE_GMTIME_R)
1217         /* If the re-entrant version is available, use it. */
1218         tmptr = gmtime_r (&current, &timedata) ;
1219 #elif defined (HAVE_GMTIME)
1220         /* Otherwise use the standard one and copy the data to local storage. */
1221         tmptr = gmtime (&current) ;
1222         memcpy (&timedata, tmptr, sizeof (timedata)) ;
1223 #else
1224         tmptr = NULL ;
1225 #endif
1226
1227         if (tmptr)
1228                 LSF_SNPRINTF (str, maxlen, "%4d-%02d-%02d %02d:%02d:%02d UTC",
1229                         1900 + timedata.tm_year, timedata.tm_mon, timedata.tm_mday,
1230                         timedata.tm_hour, timedata.tm_min, timedata.tm_sec) ;
1231         else
1232                 LSF_SNPRINTF (str, maxlen, "Unknown date") ;
1233
1234         return ;
1235 } /* psf_get_date_str */
1236
1237 int
1238 subformat_to_bytewidth (int format)
1239 {
1240         switch (format)
1241         {       case SF_FORMAT_PCM_U8 :
1242                 case SF_FORMAT_PCM_S8 :
1243                                 return 1 ;
1244                 case SF_FORMAT_PCM_16 :
1245                                 return 2 ;
1246                 case SF_FORMAT_PCM_24 :
1247                                 return 3 ;
1248                 case SF_FORMAT_PCM_32 :
1249                 case SF_FORMAT_FLOAT :
1250                                 return 4 ;
1251                 case SF_FORMAT_DOUBLE :
1252                                 return 8 ;
1253                 } ;
1254
1255         return 0 ;
1256 } /* subformat_to_bytewidth */
1257
1258 int
1259 s_bitwidth_to_subformat (int bits)
1260 {       static int array [] =
1261         {       SF_FORMAT_PCM_S8, SF_FORMAT_PCM_16, SF_FORMAT_PCM_24, SF_FORMAT_PCM_32
1262                 } ;
1263
1264         if (bits < 8 || bits > 32)
1265                 return 0 ;
1266
1267         return array [((bits + 7) / 8) - 1] ;
1268 } /* bitwidth_to_subformat */
1269
1270 int
1271 u_bitwidth_to_subformat (int bits)
1272 {       static int array [] =
1273         {       SF_FORMAT_PCM_U8, SF_FORMAT_PCM_16, SF_FORMAT_PCM_24, SF_FORMAT_PCM_32
1274                 } ;
1275
1276         if (bits < 8 || bits > 32)
1277                 return 0 ;
1278
1279         return array [((bits + 7) / 8) - 1] ;
1280 } /* bitwidth_to_subformat */
1281
1282 #endif /* PSF_LOG_PRINTF_ONLY */
1283
1284 /*
1285 ** Do not edit or modify anything in this comment block.
1286 ** The arch-tag line is a file identity tag for the GNU Arch
1287 ** revision control system.
1288 **
1289 ** arch-tag: 33e9795e-f717-461a-9feb-65d083a56395
1290 */