1 /*
2 ** Copyright (C) 1999-2019 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 <config.h>
20
21 #include <stdarg.h>
22 #include <string.h>
23 #if HAVE_UNISTD_H
24 #include <unistd.h>
25 #else
26 #include "sf_unistd.h"
27 #endif
28 #include <ctype.h>
29 #include <math.h>
30 #include <time.h>
31 #if HAVE_SYS_TIME_H
32 #include <sys/time.h>
33 #endif
34 #include "sndfile.h"
35 #include "sfendian.h"
36 #include "common.h"
37
38 #define INITIAL_HEADER_SIZE 256
39
40 /* Allocate and initialize the SF_PRIVATE struct. */
41 SF_PRIVATE *
psf_allocate(void)42 psf_allocate (void)
43 { SF_PRIVATE * psf ;
44
45 if ((psf = calloc (1, sizeof (SF_PRIVATE))) == NULL)
46 return NULL ;
47
48 if ((psf->header.ptr = calloc (1, INITIAL_HEADER_SIZE)) == NULL)
49 { free (psf) ;
50 return NULL ;
51 } ;
52 psf->header.len = INITIAL_HEADER_SIZE ;
53
54 return psf ;
55 } /* psf_allocate */
56
57 static int
psf_bump_header_allocation(SF_PRIVATE * psf,sf_count_t needed)58 psf_bump_header_allocation (SF_PRIVATE * psf, sf_count_t needed)
59 {
60 sf_count_t newlen, smallest = INITIAL_HEADER_SIZE ;
61 void * ptr ;
62
63 newlen = (needed > psf->header.len) ? 2 * SF_MAX (needed, smallest) : 2 * psf->header.len ;
64
65 if (newlen > 100 * 1024)
66 { psf_log_printf (psf, "Request for header allocation of %D denied.\n", newlen) ;
67 return 1 ;
68 }
69
70 if ((ptr = realloc (psf->header.ptr, newlen)) == NULL)
71 { psf_log_printf (psf, "realloc (%p, %D) failed\n", psf->header.ptr, newlen) ;
72 psf->error = SFE_MALLOC_FAILED ;
73 return 1 ;
74 } ;
75
76 /* Always zero-out new header memory to avoid un-initializer memory accesses. */
77 if (newlen > psf->header.len)
78 memset ((char *) ptr + psf->header.len, 0, newlen - psf->header.len) ;
79
80 psf->header.ptr = ptr ;
81 psf->header.len = newlen ;
82 return 0 ;
83 } /* psf_bump_header_allocation */
84
85 /*-----------------------------------------------------------------------------------------------
86 ** psf_log_printf allows libsndfile internal functions to print to an internal parselog which
87 ** can later be displayed.
88 ** The format specifiers are as for printf but without the field width and other modifiers.
89 ** Printing is performed to the parselog char array of the SF_PRIVATE struct.
90 ** Printing is done in such a way as to guarantee that the log never overflows the end of the
91 ** parselog array.
92 */
93
94 static inline void
log_putchar(SF_PRIVATE * psf,char ch)95 log_putchar (SF_PRIVATE *psf, char ch)
96 { if (psf->parselog.indx < SIGNED_SIZEOF (psf->parselog.buf) - 1)
97 { psf->parselog.buf [psf->parselog.indx++] = ch ;
98 psf->parselog.buf [psf->parselog.indx] = 0 ;
99 } ;
100 return ;
101 } /* log_putchar */
102
103 void
psf_log_printf(SF_PRIVATE * psf,const char * format,...)104 psf_log_printf (SF_PRIVATE *psf, const char *format, ...)
105 { va_list ap ;
106 uint32_t u ;
107 int d, tens, shift, width, width_specifier, left_align, slen ;
108 char c, *strptr, istr [5], lead_char, sign_char ;
109
110 va_start (ap, format) ;
111
112 while ((c = *format++))
113 { if (c != '%')
114 { log_putchar (psf, c) ;
115 continue ;
116 } ;
117
118 if (format [0] == '%') /* Handle %% */
119 { log_putchar (psf, '%') ;
120 format ++ ;
121 continue ;
122 } ;
123
124 sign_char = 0 ;
125 left_align = SF_FALSE ;
126 while (1)
127 { switch (format [0])
128 { case ' ' :
129 case '+' :
130 sign_char = format [0] ;
131 format ++ ;
132 continue ;
133
134 case '-' :
135 left_align = SF_TRUE ;
136 format ++ ;
137 continue ;
138
139 default : break ;
140 } ;
141
142 break ;
143 } ;
144
145 if (format [0] == 0)
146 break ;
147
148 lead_char = ' ' ;
149 if (format [0] == '0')
150 lead_char = '0' ;
151
152 width_specifier = 0 ;
153 while ((c = *format++) && isdigit (c))
154 width_specifier = width_specifier * 10 + (c - '0') ;
155
156 switch (c)
157 { case 0 : /* NULL character. */
158 va_end (ap) ;
159 return ;
160
161 case 's': /* string */
162 strptr = va_arg (ap, char *) ;
163 if (strptr == NULL)
164 break ;
165 slen = strlen (strptr) ;
166 width_specifier = width_specifier >= slen ? width_specifier - slen : 0 ;
167 if (left_align == SF_FALSE)
168 while (width_specifier -- > 0)
169 log_putchar (psf, ' ') ;
170 while (*strptr)
171 log_putchar (psf, *strptr++) ;
172 while (width_specifier -- > 0)
173 log_putchar (psf, ' ') ;
174 break ;
175
176 case 'd': /* int */
177 d = va_arg (ap, int) ;
178
179 if (d < 0)
180 { d = -d ;
181 sign_char = '-' ;
182 if (lead_char != '0' && left_align == SF_FALSE)
183 width_specifier -- ;
184 } ;
185
186 tens = 1 ;
187 width = 1 ;
188 while (d / tens >= 10)
189 { tens *= 10 ;
190 width ++ ;
191 } ;
192
193 width_specifier -= width ;
194
195 if (sign_char == ' ')
196 { log_putchar (psf, ' ') ;
197 width_specifier -- ;
198 } ;
199
200 if (left_align == SF_FALSE && lead_char != '0')
201 { if (sign_char == '+')
202 width_specifier -- ;
203
204 while (width_specifier -- > 0)
205 log_putchar (psf, lead_char) ;
206 } ;
207
208 if (sign_char == '+' || sign_char == '-')
209 { log_putchar (psf, sign_char) ;
210 width_specifier -- ;
211 } ;
212
213 if (left_align == SF_FALSE)
214 while (width_specifier -- > 0)
215 log_putchar (psf, lead_char) ;
216
217 while (tens > 0)
218 { log_putchar (psf, '0' + d / tens) ;
219 d %= tens ;
220 tens /= 10 ;
221 } ;
222
223 while (width_specifier -- > 0)
224 log_putchar (psf, lead_char) ;
225 break ;
226
227 case 'D': /* sf_count_t */
228 { sf_count_t D, Tens ;
229
230 D = va_arg (ap, sf_count_t) ;
231
232 if (D == 0)
233 { while (-- width_specifier > 0)
234 log_putchar (psf, lead_char) ;
235 log_putchar (psf, '0') ;
236 break ;
237 }
238 if (D < 0)
239 { log_putchar (psf, '-') ;
240 D = -D ;
241 } ;
242 Tens = 1 ;
243 width = 1 ;
244 while (D / Tens >= 10)
245 { Tens *= 10 ;
246 width ++ ;
247 } ;
248
249 while (width_specifier > width)
250 { log_putchar (psf, lead_char) ;
251 width_specifier-- ;
252 } ;
253
254 while (Tens > 0)
255 { log_putchar (psf, '0' + D / Tens) ;
256 D %= Tens ;
257 Tens /= 10 ;
258 } ;
259 } ;
260 break ;
261
262 case 'u': /* unsigned int */
263 u = va_arg (ap, unsigned int) ;
264
265 tens = 1 ;
266 width = 1 ;
267 while (u / tens >= 10)
268 { tens *= 10 ;
269 width ++ ;
270 } ;
271
272 width_specifier -= width ;
273
274 if (sign_char == ' ')
275 { log_putchar (psf, ' ') ;
276 width_specifier -- ;
277 } ;
278
279 if (left_align == SF_FALSE && lead_char != '0')
280 { if (sign_char == '+')
281 width_specifier -- ;
282
283 while (width_specifier -- > 0)
284 log_putchar (psf, lead_char) ;
285 } ;
286
287 if (sign_char == '+' || sign_char == '-')
288 { log_putchar (psf, sign_char) ;
289 width_specifier -- ;
290 } ;
291
292 if (left_align == SF_FALSE)
293 while (width_specifier -- > 0)
294 log_putchar (psf, lead_char) ;
295
296 while (tens > 0)
297 { log_putchar (psf, '0' + u / tens) ;
298 u %= tens ;
299 tens /= 10 ;
300 } ;
301
302 while (width_specifier -- > 0)
303 log_putchar (psf, lead_char) ;
304 break ;
305
306 case 'c': /* char */
307 c = va_arg (ap, int) & 0xFF ;
308 log_putchar (psf, c) ;
309 break ;
310
311 case 'x': /* hex */
312 case 'X': /* hex */
313 d = va_arg (ap, int) ;
314
315 if (d == 0)
316 { while (--width_specifier > 0)
317 log_putchar (psf, lead_char) ;
318 log_putchar (psf, '0') ;
319 break ;
320 } ;
321 shift = 28 ;
322 width = (width_specifier < 8) ? 8 : width_specifier ;
323 while (! ((((uint32_t) 0xF) << shift) & d))
324 { shift -= 4 ;
325 width -- ;
326 } ;
327
328 while (width > 0 && width_specifier > width)
329 { log_putchar (psf, lead_char) ;
330 width_specifier-- ;
331 } ;
332
333 while (shift >= 0)
334 { c = (d >> shift) & 0xF ;
335 log_putchar (psf, (c > 9) ? c + 'A' - 10 : c + '0') ;
336 shift -= 4 ;
337 } ;
338 break ;
339
340 case 'M': /* int2str */
341 d = va_arg (ap, int) ;
342 if (CPU_IS_LITTLE_ENDIAN)
343 { istr [0] = d & 0xFF ;
344 istr [1] = (d >> 8) & 0xFF ;
345 istr [2] = (d >> 16) & 0xFF ;
346 istr [3] = (d >> 24) & 0xFF ;
347 }
348 else
349 { istr [3] = d & 0xFF ;
350 istr [2] = (d >> 8) & 0xFF ;
351 istr [1] = (d >> 16) & 0xFF ;
352 istr [0] = (d >> 24) & 0xFF ;
353 } ;
354 istr [4] = 0 ;
355 strptr = istr ;
356 while (*strptr)
357 { c = *strptr++ ;
358 log_putchar (psf, c) ;
359 } ;
360 break ;
361
362 default :
363 log_putchar (psf, '*') ;
364 log_putchar (psf, c) ;
365 log_putchar (psf, '*') ;
366 break ;
367 } /* switch */
368 } /* while */
369
370 va_end (ap) ;
371 return ;
372 } /* psf_log_printf */
373
374 /*-----------------------------------------------------------------------------------------------
375 ** ASCII header printf functions.
376 ** Some formats (ie NIST) use ascii text in their headers.
377 ** Format specifiers are the same as the standard printf specifiers (uses vsnprintf).
378 ** If this generates a compile error on any system, the author should be notified
379 ** so an alternative vsnprintf can be provided.
380 */
381
382 void
psf_asciiheader_printf(SF_PRIVATE * psf,const char * format,...)383 psf_asciiheader_printf (SF_PRIVATE *psf, const char *format, ...)
384 { va_list argptr ;
385 int maxlen ;
386 char *start ;
387
388 if (! format)
389 return ;
390
391 maxlen = strlen ((char*) psf->header.ptr) ;
392 start = ((char*) psf->header.ptr) + maxlen ;
393 maxlen = psf->header.len - maxlen ;
394
395 va_start (argptr, format) ;
396 vsnprintf (start, maxlen, format, argptr) ;
397 va_end (argptr) ;
398
399 /* Make sure the string is properly terminated. */
400 start [maxlen - 1] = 0 ;
401
402 psf->header.indx = strlen ((char*) psf->header.ptr) ;
403
404 return ;
405 } /* psf_asciiheader_printf */
406
407 /*-----------------------------------------------------------------------------------------------
408 ** Binary header writing functions. Returns number of bytes written.
409 **
410 ** Format specifiers for psf_binheader_writef are as follows
411 ** m - marker - four bytes - no endian manipulation
412 **
413 ** e - all following numerical values will be little endian
414 ** E - all following numerical values will be big endian
415 **
416 ** t - all following O types will be truncated to 4 bytes
417 ** T - switch off truncation of all following O types
418 **
419 ** 1 - single byte value
420 ** 2 - two byte value
421 ** 3 - three byte value
422 ** 4 - four byte value
423 ** 8 - eight byte value (sometimes written as 4 bytes)
424 **
425 ** s - string preceded by a four byte length
426 ** S - string including null terminator
427 ** p - a Pascal string
428 **
429 ** f - floating point data
430 ** d - double precision floating point data
431 ** h - 16 binary bytes value
432 **
433 ** b - binary data (see below)
434 ** z - zero bytes (ses below)
435 ** j - jump forwards or backwards
436 **
437 ** To write a word followed by an int (both little endian) use:
438 ** psf_binheader_writef ("e24", wordval, longval) ;
439 **
440 ** To write binary data use:
441 ** psf_binheader_writef ("b", &bindata, sizeof (bindata)) ;
442 **
443 ** To write N zero bytes use:
444 ** NOTE: due to platform issues (ie x86-64) you should cast the
445 ** argument to size_t or ensure the variable type is size_t.
446 ** psf_binheader_writef ("z", N) ;
447 */
448
449 /* These macros may seem a bit messy but do prevent problems with processors which
450 ** seg. fault when asked to write an int or short to a non-int/short aligned address.
451 */
452
453 static inline void
header_put_byte(SF_PRIVATE * psf,char x)454 header_put_byte (SF_PRIVATE *psf, char x)
455 { psf->header.ptr [psf->header.indx++] = x ;
456 } /* header_put_byte */
457
458 #if (CPU_IS_BIG_ENDIAN == 1)
459 static inline void
header_put_marker(SF_PRIVATE * psf,int x)460 header_put_marker (SF_PRIVATE *psf, int x)
461 { psf->header.ptr [psf->header.indx++] = (x >> 24) ;
462 psf->header.ptr [psf->header.indx++] = (x >> 16) ;
463 psf->header.ptr [psf->header.indx++] = (x >> 8) ;
464 psf->header.ptr [psf->header.indx++] = x ;
465 } /* header_put_marker */
466
467 #elif (CPU_IS_LITTLE_ENDIAN == 1)
468 static inline void
header_put_marker(SF_PRIVATE * psf,int x)469 header_put_marker (SF_PRIVATE *psf, int x)
470 { psf->header.ptr [psf->header.indx++] = x ;
471 psf->header.ptr [psf->header.indx++] = (x >> 8) ;
472 psf->header.ptr [psf->header.indx++] = (x >> 16) ;
473 psf->header.ptr [psf->header.indx++] = (x >> 24) ;
474 } /* header_put_marker */
475
476 #else
477 # error "Cannot determine endian-ness of processor."
478 #endif
479
480
481 static inline void
header_put_be_short(SF_PRIVATE * psf,int x)482 header_put_be_short (SF_PRIVATE *psf, int x)
483 { psf->header.ptr [psf->header.indx++] = (x >> 8) ;
484 psf->header.ptr [psf->header.indx++] = x ;
485 } /* header_put_be_short */
486
487 static inline void
header_put_le_short(SF_PRIVATE * psf,int x)488 header_put_le_short (SF_PRIVATE *psf, int x)
489 { psf->header.ptr [psf->header.indx++] = x ;
490 psf->header.ptr [psf->header.indx++] = (x >> 8) ;
491 } /* header_put_le_short */
492
493 static inline void
header_put_be_3byte(SF_PRIVATE * psf,int x)494 header_put_be_3byte (SF_PRIVATE *psf, int x)
495 { psf->header.ptr [psf->header.indx++] = (x >> 16) ;
496 psf->header.ptr [psf->header.indx++] = (x >> 8) ;
497 psf->header.ptr [psf->header.indx++] = x ;
498 } /* header_put_be_3byte */
499
500 static inline void
header_put_le_3byte(SF_PRIVATE * psf,int x)501 header_put_le_3byte (SF_PRIVATE *psf, int x)
502 { psf->header.ptr [psf->header.indx++] = x ;
503 psf->header.ptr [psf->header.indx++] = (x >> 8) ;
504 psf->header.ptr [psf->header.indx++] = (x >> 16) ;
505 } /* header_put_le_3byte */
506
507 static inline void
header_put_be_int(SF_PRIVATE * psf,int x)508 header_put_be_int (SF_PRIVATE *psf, int x)
509 { psf->header.ptr [psf->header.indx++] = (x >> 24) ;
510 psf->header.ptr [psf->header.indx++] = (x >> 16) ;
511 psf->header.ptr [psf->header.indx++] = (x >> 8) ;
512 psf->header.ptr [psf->header.indx++] = x ;
513 } /* header_put_be_int */
514
515 static inline void
header_put_le_int(SF_PRIVATE * psf,int x)516 header_put_le_int (SF_PRIVATE *psf, int x)
517 { psf->header.ptr [psf->header.indx++] = x ;
518 psf->header.ptr [psf->header.indx++] = (x >> 8) ;
519 psf->header.ptr [psf->header.indx++] = (x >> 16) ;
520 psf->header.ptr [psf->header.indx++] = (x >> 24) ;
521 } /* header_put_le_int */
522
523 #if (SIZEOF_SF_COUNT_T == 8)
524
525 static inline void
header_put_be_8byte(SF_PRIVATE * psf,sf_count_t x)526 header_put_be_8byte (SF_PRIVATE *psf, sf_count_t x)
527 { psf->header.ptr [psf->header.indx++] = (x >> 56) ;
528 psf->header.ptr [psf->header.indx++] = (x >> 48) ;
529 psf->header.ptr [psf->header.indx++] = (x >> 40) ;
530 psf->header.ptr [psf->header.indx++] = (x >> 32) ;
531 psf->header.ptr [psf->header.indx++] = (x >> 24) ;
532 psf->header.ptr [psf->header.indx++] = (x >> 16) ;
533 psf->header.ptr [psf->header.indx++] = (x >> 8) ;
534 psf->header.ptr [psf->header.indx++] = x ;
535 } /* header_put_be_8byte */
536
537 static inline void
header_put_le_8byte(SF_PRIVATE * psf,sf_count_t x)538 header_put_le_8byte (SF_PRIVATE *psf, sf_count_t x)
539 { psf->header.ptr [psf->header.indx++] = x ;
540 psf->header.ptr [psf->header.indx++] = (x >> 8) ;
541 psf->header.ptr [psf->header.indx++] = (x >> 16) ;
542 psf->header.ptr [psf->header.indx++] = (x >> 24) ;
543 psf->header.ptr [psf->header.indx++] = (x >> 32) ;
544 psf->header.ptr [psf->header.indx++] = (x >> 40) ;
545 psf->header.ptr [psf->header.indx++] = (x >> 48) ;
546 psf->header.ptr [psf->header.indx++] = (x >> 56) ;
547 } /* header_put_le_8byte */
548
549 #else
550 #error "SIZEOF_SF_COUNT_T != 8"
551 #endif
552
553 int
psf_binheader_writef(SF_PRIVATE * psf,const char * format,...)554 psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...)
555 { va_list argptr ;
556 sf_count_t countdata ;
557 unsigned long longdata ;
558 unsigned int data ;
559 float floatdata ;
560 double doubledata ;
561 void *bindata ;
562 size_t size ;
563 char c, *strptr ;
564 int count = 0, trunc_8to4 = SF_FALSE ;
565
566 if (! format)
567 return psf_ftell (psf) ;
568
569 va_start (argptr, format) ;
570
571 while ((c = *format++))
572 {
573 if (psf->header.indx + 16 >= psf->header.len && psf_bump_header_allocation (psf, 16))
574 return count ;
575
576 switch (c)
577 { case ' ' : /* Do nothing. Just used to space out format string. */
578 break ;
579
580 case 'e' : /* All conversions are now from LE to host. */
581 psf->rwf_endian = SF_ENDIAN_LITTLE ;
582 break ;
583
584 case 'E' : /* All conversions are now from BE to host. */
585 psf->rwf_endian = SF_ENDIAN_BIG ;
586 break ;
587
588 case 't' : /* All 8 byte values now get written as 4 bytes. */
589 trunc_8to4 = SF_TRUE ;
590 break ;
591
592 case 'T' : /* All 8 byte values now get written as 8 bytes. */
593 trunc_8to4 = SF_FALSE ;
594 break ;
595
596 case 'm' :
597 data = va_arg (argptr, unsigned int) ;
598 header_put_marker (psf, data) ;
599 count += 4 ;
600 break ;
601
602 case '1' :
603 data = va_arg (argptr, unsigned int) ;
604 header_put_byte (psf, data) ;
605 count += 1 ;
606 break ;
607
608 case '2' :
609 data = va_arg (argptr, unsigned int) ;
610 if (psf->rwf_endian == SF_ENDIAN_BIG)
611 { header_put_be_short (psf, data) ;
612 }
613 else
614 { header_put_le_short (psf, data) ;
615 } ;
616 count += 2 ;
617 break ;
618
619 case '3' : /* tribyte */
620 data = va_arg (argptr, unsigned int) ;
621 if (psf->rwf_endian == SF_ENDIAN_BIG)
622 { header_put_be_3byte (psf, data) ;
623 }
624 else
625 { header_put_le_3byte (psf, data) ;
626 } ;
627 count += 3 ;
628 break ;
629
630 case '4' :
631 data = va_arg (argptr, unsigned int) ;
632 if (psf->rwf_endian == SF_ENDIAN_BIG)
633 { header_put_be_int (psf, data) ;
634 }
635 else
636 { header_put_le_int (psf, data) ;
637 } ;
638 count += 4 ;
639 break ;
640
641 case '8' :
642 countdata = va_arg (argptr, sf_count_t) ;
643 if (psf->rwf_endian == SF_ENDIAN_BIG && trunc_8to4 == SF_FALSE)
644 { header_put_be_8byte (psf, countdata) ;
645 count += 8 ;
646 }
647 else if (psf->rwf_endian == SF_ENDIAN_LITTLE && trunc_8to4 == SF_FALSE)
648 { header_put_le_8byte (psf, countdata) ;
649 count += 8 ;
650 }
651 else if (psf->rwf_endian == SF_ENDIAN_BIG && trunc_8to4 == SF_TRUE)
652 { longdata = countdata & 0xFFFFFFFF ;
653 header_put_be_int (psf, longdata) ;
654 count += 4 ;
655 }
656 else if (psf->rwf_endian == SF_ENDIAN_LITTLE && trunc_8to4 == SF_TRUE)
657 { longdata = countdata & 0xFFFFFFFF ;
658 header_put_le_int (psf, longdata) ;
659 count += 4 ;
660 }
661 break ;
662
663 case 'f' :
664 /* Floats are passed as doubles. Is this always true? */
665 floatdata = (float) va_arg (argptr, double) ;
666 if (psf->rwf_endian == SF_ENDIAN_BIG)
667 float32_be_write (floatdata, psf->header.ptr + psf->header.indx) ;
668 else
669 float32_le_write (floatdata, psf->header.ptr + psf->header.indx) ;
670 psf->header.indx += 4 ;
671 count += 4 ;
672 break ;
673
674 case 'd' :
675 doubledata = va_arg (argptr, double) ;
676 if (psf->rwf_endian == SF_ENDIAN_BIG)
677 double64_be_write (doubledata, psf->header.ptr + psf->header.indx) ;
678 else
679 double64_le_write (doubledata, psf->header.ptr + psf->header.indx) ;
680 psf->header.indx += 8 ;
681 count += 8 ;
682 break ;
683
684 case 's' :
685 /* Write a C string (guaranteed to have a zero terminator). */
686 strptr = va_arg (argptr, char *) ;
687 size = strlen (strptr) + 1 ;
688
689 if (psf->header.indx + 4 + (sf_count_t) size + (sf_count_t) (size & 1) > psf->header.len && psf_bump_header_allocation (psf, 4 + size + (size & 1)))
690 return count ;
691
692 if (psf->rwf_endian == SF_ENDIAN_BIG)
693 header_put_be_int (psf, size + (size & 1)) ;
694 else
695 header_put_le_int (psf, size + (size & 1)) ;
696 memcpy (&(psf->header.ptr [psf->header.indx]), strptr, size) ;
697 size += (size & 1) ;
698 psf->header.indx += size ;
699 psf->header.ptr [psf->header.indx - 1] = 0 ;
700 count += 4 + size ;
701 break ;
702
703 case 'S' :
704 /*
705 ** Write an AIFF style string (no zero terminator but possibly
706 ** an extra pad byte if the string length is odd).
707 */
708 strptr = va_arg (argptr, char *) ;
709 size = strlen (strptr) ;
710 if (psf->header.indx + 4 + (sf_count_t) size + (sf_count_t) (size & 1) > psf->header.len && psf_bump_header_allocation (psf, 4 + size + (size & 1)))
711 return count ;
712 if (psf->rwf_endian == SF_ENDIAN_BIG)
713 header_put_be_int (psf, size) ;
714 else
715 header_put_le_int (psf, size) ;
716 memcpy (&(psf->header.ptr [psf->header.indx]), strptr, size + (size & 1)) ;
717 size += (size & 1) ;
718 psf->header.indx += size ;
719 count += 4 + size ;
720 break ;
721
722 case 'p' :
723 /* Write a PASCAL string (as used by AIFF files).
724 */
725 strptr = va_arg (argptr, char *) ;
726 size = strlen (strptr) ;
727 size = (size & 1) ? size : size + 1 ;
728 size = (size > 254) ? 254 : size ;
729
730 if (psf->header.indx + 1 + (sf_count_t) size > psf->header.len && psf_bump_header_allocation (psf, 1 + size))
731 return count ;
732
733 header_put_byte (psf, size) ;
734 memcpy (&(psf->header.ptr [psf->header.indx]), strptr, size) ;
735 psf->header.indx += size ;
736 count += 1 + size ;
737 break ;
738
739 case 'b' :
740 bindata = va_arg (argptr, void *) ;
741 size = va_arg (argptr, size_t) ;
742
743 if (psf->header.indx + (sf_count_t) size > psf->header.len && psf_bump_header_allocation (psf, size))
744 return count ;
745
746 memcpy (&(psf->header.ptr [psf->header.indx]), bindata, size) ;
747 psf->header.indx += size ;
748 count += size ;
749 break ;
750
751 case 'z' :
752 size = va_arg (argptr, size_t) ;
753
754 if (psf->header.indx + (sf_count_t) size > psf->header.len && psf_bump_header_allocation (psf, size))
755 return count ;
756
757 count += size ;
758 while (size)
759 { psf->header.ptr [psf->header.indx] = 0 ;
760 psf->header.indx ++ ;
761 size -- ;
762 } ;
763 break ;
764
765 case 'h' :
766 bindata = va_arg (argptr, void *) ;
767 memcpy (&(psf->header.ptr [psf->header.indx]), bindata, 16) ;
768 psf->header.indx += 16 ;
769 count += 16 ;
770 break ;
771
772 case 'j' : /* Jump forwards/backwards by specified amount. */
773 size = va_arg (argptr, size_t) ;
774
775 if (psf->header.indx + (sf_count_t) size > psf->header.len && psf_bump_header_allocation (psf, size))
776 return count ;
777
778 psf->header.indx += size ;
779 count += size ;
780 break ;
781
782 case 'o' : /* Jump to specified offset. */
783 size = va_arg (argptr, size_t) ;
784
785 if ((sf_count_t) size >= psf->header.len && psf_bump_header_allocation (psf, size))
786 return count ;
787
788 psf->header.indx = size ;
789 break ;
790
791 default :
792 psf_log_printf (psf, "*** Invalid format specifier `%c'\n", c) ;
793 psf->error = SFE_INTERNAL ;
794 break ;
795 } ;
796 } ;
797
798 va_end (argptr) ;
799 return count ;
800 } /* psf_binheader_writef */
801
802 /*-----------------------------------------------------------------------------------------------
803 ** Binary header reading functions. Returns number of bytes read.
804 **
805 ** Format specifiers are the same as for header write function above with the following
806 ** additions:
807 **
808 ** p - jump a given number of position from start of file.
809 **
810 ** If format is NULL, psf_binheader_readf returns the current offset.
811 */
812
813 #if (CPU_IS_BIG_ENDIAN == 1)
814 #define GET_MARKER(ptr) ( (((uint32_t) (ptr) [0]) << 24) | ((ptr) [1] << 16) | \
815 ((ptr) [2] << 8) | ((ptr) [3]))
816
817 #elif (CPU_IS_LITTLE_ENDIAN == 1)
818 #define GET_MARKER(ptr) ( ((ptr) [0]) | ((ptr) [1] << 8) | \
819 ((ptr) [2] << 16) | (((uint32_t) (ptr) [3]) << 24))
820
821 #else
822 # error "Cannot determine endian-ness of processor."
823 #endif
824
825 #define GET_LE_SHORT(ptr) (((ptr) [1] << 8) | ((ptr) [0]))
826 #define GET_BE_SHORT(ptr) (((ptr) [0] << 8) | ((ptr) [1]))
827
828 #define GET_LE_3BYTE(ptr) ( ((ptr) [2] << 16) | ((ptr) [1] << 8) | ((ptr) [0]))
829 #define GET_BE_3BYTE(ptr) ( ((ptr) [0] << 16) | ((ptr) [1] << 8) | ((ptr) [2]))
830
831 #define GET_LE_INT(ptr) ( ((ptr) [3] << 24) | ((ptr) [2] << 16) | \
832 ((ptr) [1] << 8) | ((ptr) [0]))
833
834 #define GET_BE_INT(ptr) ( ((ptr) [0] << 24) | ((ptr) [1] << 16) | \
835 ((ptr) [2] << 8) | ((ptr) [3]))
836
837 #define GET_LE_8BYTE(ptr) ( (((sf_count_t) (ptr) [7]) << 56) | (((sf_count_t) (ptr) [6]) << 48) | \
838 (((sf_count_t) (ptr) [5]) << 40) | (((sf_count_t) (ptr) [4]) << 32) | \
839 (((sf_count_t) (ptr) [3]) << 24) | (((sf_count_t) (ptr) [2]) << 16) | \
840 (((sf_count_t) (ptr) [1]) << 8) | ((ptr) [0]))
841
842 #define GET_BE_8BYTE(ptr) ( (((sf_count_t) (ptr) [0]) << 56) | (((sf_count_t) (ptr) [1]) << 48) | \
843 (((sf_count_t) (ptr) [2]) << 40) | (((sf_count_t) (ptr) [3]) << 32) | \
844 (((sf_count_t) (ptr) [4]) << 24) | (((sf_count_t) (ptr) [5]) << 16) | \
845 (((sf_count_t) (ptr) [6]) << 8) | ((ptr) [7]))
846
847
848
849 static int
header_read(SF_PRIVATE * psf,void * ptr,int bytes)850 header_read (SF_PRIVATE *psf, void *ptr, int bytes)
851 { int count = 0 ;
852
853 if (psf->header.indx + bytes >= psf->header.len && psf_bump_header_allocation (psf, bytes))
854 return count ;
855
856 if (psf->header.indx + bytes > psf->header.end)
857 { count = psf_fread (psf->header.ptr + psf->header.end, 1, bytes - (psf->header.end - psf->header.indx), psf) ;
858 if (count != bytes - (int) (psf->header.end - psf->header.indx))
859 { psf_log_printf (psf, "Error : psf_fread returned short count.\n") ;
860 return count ;
861 } ;
862 psf->header.end += count ;
863 } ;
864
865 memcpy (ptr, psf->header.ptr + psf->header.indx, bytes) ;
866 psf->header.indx += bytes ;
867
868 return bytes ;
869 } /* header_read */
870
871 static void
header_seek(SF_PRIVATE * psf,sf_count_t position,int whence)872 header_seek (SF_PRIVATE *psf, sf_count_t position, int whence)
873 {
874 switch (whence)
875 { case SEEK_SET :
876 if (psf->header.indx + position >= psf->header.len)
877 psf_bump_header_allocation (psf, position) ;
878 if (position > psf->header.len)
879 { /* Too much header to cache so just seek instead. */
880 psf->header.indx = psf->header.end ;
881 psf_fseek (psf, position, whence) ;
882 return ;
883 } ;
884 if (position > psf->header.end)
885 psf->header.end += psf_fread (psf->header.ptr + psf->header.end, 1, position - psf->header.end, psf) ;
886 psf->header.indx = position ;
887 break ;
888
889 case SEEK_CUR :
890 if (psf->header.indx + position >= psf->header.len)
891 psf_bump_header_allocation (psf, position) ;
892
893 if (psf->header.indx + position < 0)
894 break ;
895
896 if (psf->header.indx >= psf->header.len)
897 { psf_fseek (psf, position, whence) ;
898 return ;
899 } ;
900
901 if (psf->header.indx + position <= psf->header.end)
902 { psf->header.indx += position ;
903 break ;
904 } ;
905
906 if (psf->header.indx + position > psf->header.len)
907 { /* Need to jump this without caching it. */
908 psf->header.indx = psf->header.end ;
909 psf_fseek (psf, position, SEEK_CUR) ;
910 break ;
911 } ;
912
913 psf->header.end += psf_fread (psf->header.ptr + psf->header.end, 1, position - (psf->header.end - psf->header.indx), psf) ;
914 psf->header.indx = psf->header.end ;
915 break ;
916
917 case SEEK_END :
918 default :
919 psf_log_printf (psf, "Bad whence param in header_seek().\n") ;
920 break ;
921 } ;
922
923 return ;
924 } /* header_seek */
925
926 static int
header_gets(SF_PRIVATE * psf,char * ptr,int bufsize)927 header_gets (SF_PRIVATE *psf, char *ptr, int bufsize)
928 { int k ;
929
930 if (psf->header.indx + bufsize >= psf->header.len && psf_bump_header_allocation (psf, bufsize))
931 return 0 ;
932
933 for (k = 0 ; k < bufsize - 1 ; k++)
934 { if (psf->header.indx < psf->header.end)
935 { ptr [k] = psf->header.ptr [psf->header.indx] ;
936 psf->header.indx ++ ;
937 }
938 else
939 { psf->header.end += psf_fread (psf->header.ptr + psf->header.end, 1, 1, psf) ;
940 ptr [k] = psf->header.ptr [psf->header.indx] ;
941 psf->header.indx = psf->header.end ;
942 } ;
943
944 if (ptr [k] == '\n')
945 break ;
946 } ;
947
948 ptr [k] = 0 ;
949
950 return k ;
951 } /* header_gets */
952
953 int
psf_binheader_readf(SF_PRIVATE * psf,char const * format,...)954 psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...)
955 { va_list argptr ;
956 sf_count_t *countptr, countdata ;
957 unsigned char *ucptr, sixteen_bytes [16] ;
958 unsigned int *intptr, intdata ;
959 unsigned short *shortptr ;
960 char *charptr ;
961 float *floatptr ;
962 double *doubleptr ;
963 char c ;
964 int byte_count = 0, count = 0 ;
965
966 if (! format)
967 return psf_ftell (psf) ;
968
969 va_start (argptr, format) ;
970
971 while ((c = *format++))
972 {
973 if (psf->header.indx + 16 >= psf->header.len && psf_bump_header_allocation (psf, 16))
974 return count ;
975
976 switch (c)
977 { case 'e' : /* All conversions are now from LE to host. */
978 psf->rwf_endian = SF_ENDIAN_LITTLE ;
979 break ;
980
981 case 'E' : /* All conversions are now from BE to host. */
982 psf->rwf_endian = SF_ENDIAN_BIG ;
983 break ;
984
985 case 'm' : /* 4 byte marker value eg 'RIFF' */
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 *intptr = GET_MARKER (ucptr) ;
991 break ;
992
993 case 'h' :
994 intptr = va_arg (argptr, unsigned int*) ;
995 *intptr = 0 ;
996 ucptr = (unsigned char*) intptr ;
997 byte_count += header_read (psf, sixteen_bytes, sizeof (sixteen_bytes)) ;
998 { int k ;
999 intdata = 0 ;
1000 for (k = 0 ; k < 16 ; k++)
1001 intdata ^= sixteen_bytes [k] << k ;
1002 }
1003 *intptr = intdata ;
1004 break ;
1005
1006 case '1' :
1007 charptr = va_arg (argptr, char*) ;
1008 *charptr = 0 ;
1009 byte_count += header_read (psf, charptr, sizeof (char)) ;
1010 break ;
1011
1012 case '2' : /* 2 byte value with the current endian-ness */
1013 shortptr = va_arg (argptr, unsigned short*) ;
1014 *shortptr = 0 ;
1015 ucptr = (unsigned char*) shortptr ;
1016 byte_count += header_read (psf, ucptr, sizeof (short)) ;
1017 if (psf->rwf_endian == SF_ENDIAN_BIG)
1018 *shortptr = GET_BE_SHORT (ucptr) ;
1019 else
1020 *shortptr = GET_LE_SHORT (ucptr) ;
1021 break ;
1022
1023 case '3' : /* 3 byte value with the current endian-ness */
1024 intptr = va_arg (argptr, unsigned int*) ;
1025 *intptr = 0 ;
1026 byte_count += header_read (psf, sixteen_bytes, 3) ;
1027 if (psf->rwf_endian == SF_ENDIAN_BIG)
1028 *intptr = GET_BE_3BYTE (sixteen_bytes) ;
1029 else
1030 *intptr = GET_LE_3BYTE (sixteen_bytes) ;
1031 break ;
1032
1033 case '4' : /* 4 byte value with the current endian-ness */
1034 intptr = va_arg (argptr, unsigned int*) ;
1035 *intptr = 0 ;
1036 ucptr = (unsigned char*) intptr ;
1037 byte_count += header_read (psf, ucptr, sizeof (int)) ;
1038 if (psf->rwf_endian == SF_ENDIAN_BIG)
1039 *intptr = psf_get_be32 (ucptr, 0) ;
1040 else
1041 *intptr = psf_get_le32 (ucptr, 0) ;
1042 break ;
1043
1044 case '8' : /* 8 byte value with the current endian-ness */
1045 countptr = va_arg (argptr, sf_count_t *) ;
1046 *countptr = 0 ;
1047 byte_count += header_read (psf, sixteen_bytes, 8) ;
1048 if (psf->rwf_endian == SF_ENDIAN_BIG)
1049 countdata = psf_get_be64 (sixteen_bytes, 0) ;
1050 else
1051 countdata = psf_get_le64 (sixteen_bytes, 0) ;
1052 *countptr = countdata ;
1053 break ;
1054
1055 case 'f' : /* Float conversion */
1056 floatptr = va_arg (argptr, float *) ;
1057 *floatptr = 0.0 ;
1058 byte_count += header_read (psf, floatptr, sizeof (float)) ;
1059 if (psf->rwf_endian == SF_ENDIAN_BIG)
1060 *floatptr = float32_be_read ((unsigned char*) floatptr) ;
1061 else
1062 *floatptr = float32_le_read ((unsigned char*) floatptr) ;
1063 break ;
1064
1065 case 'd' : /* double conversion */
1066 doubleptr = va_arg (argptr, double *) ;
1067 *doubleptr = 0.0 ;
1068 byte_count += header_read (psf, doubleptr, sizeof (double)) ;
1069 if (psf->rwf_endian == SF_ENDIAN_BIG)
1070 *doubleptr = double64_be_read ((unsigned char*) doubleptr) ;
1071 else
1072 *doubleptr = double64_le_read ((unsigned char*) doubleptr) ;
1073 break ;
1074
1075 case 's' :
1076 psf_log_printf (psf, "Format conversion 's' not implemented yet.\n") ;
1077 /*
1078 strptr = va_arg (argptr, char *) ;
1079 size = strlen (strptr) + 1 ;
1080 size += (size & 1) ;
1081 longdata = H2LE_32 (size) ;
1082 get_int (psf, longdata) ;
1083 memcpy (&(psf->header.ptr [psf->header.indx]), strptr, size) ;
1084 psf->header.indx += size ;
1085 */
1086 break ;
1087
1088 case 'b' : /* Raw bytes */
1089 charptr = va_arg (argptr, char*) ;
1090 count = va_arg (argptr, size_t) ;
1091 memset (charptr, 0, count) ;
1092 byte_count += header_read (psf, charptr, count) ;
1093 break ;
1094
1095 case 'G' :
1096 charptr = va_arg (argptr, char*) ;
1097 count = va_arg (argptr, size_t) ;
1098 memset (charptr, 0, count) ;
1099
1100 if (psf->header.indx + count >= psf->header.len && psf_bump_header_allocation (psf, count))
1101 return 0 ;
1102
1103 byte_count += header_gets (psf, charptr, count) ;
1104 break ;
1105
1106 case 'z' :
1107 psf_log_printf (psf, "Format conversion 'z' not implemented yet.\n") ;
1108 /*
1109 size = va_arg (argptr, size_t) ;
1110 while (size)
1111 { psf->header.ptr [psf->header.indx] = 0 ;
1112 psf->header.indx ++ ;
1113 size -- ;
1114 } ;
1115 */
1116 break ;
1117
1118 case 'p' : /* Seek to position from start. */
1119 count = va_arg (argptr, size_t) ;
1120 header_seek (psf, count, SEEK_SET) ;
1121 byte_count = count ;
1122 break ;
1123
1124 case 'j' : /* Seek to position from current position. */
1125 count = va_arg (argptr, size_t) ;
1126 header_seek (psf, count, SEEK_CUR) ;
1127 byte_count += count ;
1128 break ;
1129
1130 default :
1131 psf_log_printf (psf, "*** Invalid format specifier `%c'\n", c) ;
1132 psf->error = SFE_INTERNAL ;
1133 break ;
1134 } ;
1135 } ;
1136
1137 va_end (argptr) ;
1138
1139 return byte_count ;
1140 } /* psf_binheader_readf */
1141
1142 /*-----------------------------------------------------------------------------------------------
1143 */
1144
1145 sf_count_t
psf_default_seek(SF_PRIVATE * psf,int UNUSED (mode),sf_count_t samples_from_start)1146 psf_default_seek (SF_PRIVATE *psf, int UNUSED (mode), sf_count_t samples_from_start)
1147 { sf_count_t position, retval ;
1148
1149 if (! (psf->blockwidth && psf->dataoffset >= 0))
1150 { psf->error = SFE_BAD_SEEK ;
1151 return PSF_SEEK_ERROR ;
1152 } ;
1153
1154 if (! psf->sf.seekable)
1155 { psf->error = SFE_NOT_SEEKABLE ;
1156 return PSF_SEEK_ERROR ;
1157 } ;
1158
1159 position = psf->dataoffset + psf->blockwidth * samples_from_start ;
1160
1161 if ((retval = psf_fseek (psf, position, SEEK_SET)) != position)
1162 { psf->error = SFE_SEEK_FAILED ;
1163 return PSF_SEEK_ERROR ;
1164 } ;
1165
1166 return samples_from_start ;
1167 } /* psf_default_seek */
1168
1169 /*-----------------------------------------------------------------------------------------------
1170 */
1171
1172 void
psf_hexdump(const void * ptr,int len)1173 psf_hexdump (const void *ptr, int len)
1174 { const char *data ;
1175 char ascii [17] ;
1176 int k, m ;
1177
1178 if ((data = ptr) == NULL)
1179 return ;
1180 if (len <= 0)
1181 return ;
1182
1183 puts ("") ;
1184 for (k = 0 ; k < len ; k += 16)
1185 { memset (ascii, ' ', sizeof (ascii)) ;
1186
1187 printf ("%08X: ", k) ;
1188 for (m = 0 ; m < 16 && k + m < len ; m++)
1189 { printf (m == 8 ? " %02X " : "%02X ", data [k + m] & 0xFF) ;
1190 ascii [m] = psf_isprint (data [k + m]) ? data [k + m] : '.' ;
1191 } ;
1192
1193 if (m <= 8) printf (" ") ;
1194 for ( ; m < 16 ; m++) printf (" ") ;
1195
1196 ascii [16] = 0 ;
1197 printf (" %s\n", ascii) ;
1198 } ;
1199
1200 puts ("") ;
1201 } /* psf_hexdump */
1202
1203 void
psf_log_SF_INFO(SF_PRIVATE * psf)1204 psf_log_SF_INFO (SF_PRIVATE *psf)
1205 { psf_log_printf (psf, "---------------------------------\n") ;
1206
1207 psf_log_printf (psf, " Sample rate : %d\n", psf->sf.samplerate) ;
1208 if (psf->sf.frames == SF_COUNT_MAX)
1209 psf_log_printf (psf, " Frames : unknown\n") ;
1210 else
1211 psf_log_printf (psf, " Frames : %D\n", psf->sf.frames) ;
1212 psf_log_printf (psf, " Channels : %d\n", psf->sf.channels) ;
1213
1214 psf_log_printf (psf, " Format : 0x%X\n", psf->sf.format) ;
1215 psf_log_printf (psf, " Sections : %d\n", psf->sf.sections) ;
1216 psf_log_printf (psf, " Seekable : %s\n", psf->sf.seekable ? "TRUE" : "FALSE") ;
1217
1218 psf_log_printf (psf, "---------------------------------\n") ;
1219 } /* psf_dump_SFINFO */
1220
1221 /*========================================================================================
1222 */
1223
1224 void*
psf_memset(void * s,int c,sf_count_t len)1225 psf_memset (void *s, int c, sf_count_t len)
1226 { char *ptr ;
1227 int setcount ;
1228
1229 ptr = (char *) s ;
1230
1231 while (len > 0)
1232 { setcount = (len > 0x10000000) ? 0x10000000 : (int) len ;
1233
1234 memset (ptr, c, setcount) ;
1235
1236 ptr += setcount ;
1237 len -= setcount ;
1238 } ;
1239
1240 return s ;
1241 } /* psf_memset */
1242
1243
1244 /*
1245 ** Clang refuses to do sizeof (SF_CUES_VAR (cue_count)) so we have to manually
1246 ** bodgy something up instead.
1247 */
1248
1249 typedef SF_CUES_VAR (0) SF_CUES_0 ;
1250
1251 /* calculate size of SF_CUES struct given number of cues */
1252 #define SF_CUES_VAR_SIZE(count) (sizeof (SF_CUES_0) + count * sizeof (SF_CUE_POINT))
1253
1254 /* calculate number of cues in SF_CUES struct given data size */
1255 #define SF_CUES_COUNT(datasize) (((datasize) - sizeof (uint32_t)) / sizeof (SF_CUE_POINT))
1256
1257 SF_CUES *
psf_cues_alloc(uint32_t cue_count)1258 psf_cues_alloc (uint32_t cue_count)
1259 { SF_CUES *pcues = calloc (1, SF_CUES_VAR_SIZE (cue_count)) ;
1260
1261 pcues->cue_count = cue_count ;
1262 return pcues ;
1263 } /* psf_cues_alloc */
1264
1265 SF_CUES *
psf_cues_dup(const void * ptr,size_t datasize)1266 psf_cues_dup (const void * ptr, size_t datasize)
1267 { const SF_CUES *pcues = ptr ;
1268 SF_CUES *pnew = NULL ;
1269
1270 if (pcues->cue_count <= SF_CUES_COUNT (datasize))
1271 { /* check that passed-in datasize is consistent with cue_count in passed-in SF_CUES struct */
1272 pnew = psf_cues_alloc (pcues->cue_count) ;
1273 memcpy (pnew, pcues, SF_CUES_VAR_SIZE (pcues->cue_count)) ;
1274 }
1275
1276 return pnew ;
1277 } /* psf_cues_dup */
1278
1279 void
psf_get_cues(SF_PRIVATE * psf,void * data,size_t datasize)1280 psf_get_cues (SF_PRIVATE * psf, void * data, size_t datasize)
1281 {
1282 if (psf->cues)
1283 { uint32_t cue_count = SF_CUES_COUNT (datasize) ;
1284
1285 cue_count = SF_MIN (cue_count, psf->cues->cue_count) ;
1286 memcpy (data, psf->cues, SF_CUES_VAR_SIZE (cue_count)) ;
1287 ((SF_CUES*) data)->cue_count = cue_count ;
1288 } ;
1289
1290 return ;
1291 } /* psf_get_cues */
1292
1293
1294 SF_INSTRUMENT *
psf_instrument_alloc(void)1295 psf_instrument_alloc (void)
1296 { SF_INSTRUMENT *instr ;
1297
1298 instr = calloc (1, sizeof (SF_INSTRUMENT)) ;
1299
1300 if (instr == NULL)
1301 return NULL ;
1302
1303 /* Set non-zero default values. */
1304 instr->basenote = -1 ;
1305 instr->velocity_lo = -1 ;
1306 instr->velocity_hi = -1 ;
1307 instr->key_lo = -1 ;
1308 instr->key_hi = -1 ;
1309
1310 return instr ;
1311 } /* psf_instrument_alloc */
1312
1313 void
psf_sanitize_string(char * cptr,int len)1314 psf_sanitize_string (char * cptr, int len)
1315 {
1316 do
1317 {
1318 len -- ;
1319 cptr [len] = psf_isprint (cptr [len]) ? cptr [len] : '.' ;
1320 }
1321 while (len > 0) ;
1322 } /* psf_sanitize_string */
1323
1324 void
psf_get_date_str(char * str,int maxlen)1325 psf_get_date_str (char *str, int maxlen)
1326 { time_t current ;
1327 struct tm timedata, *tmptr ;
1328
1329 time (¤t) ;
1330
1331 #if defined (HAVE_GMTIME_R)
1332 /* If the re-entrant version is available, use it. */
1333 tmptr = gmtime_r (¤t, &timedata) ;
1334 #elif defined (HAVE_GMTIME)
1335 /* Otherwise use the standard one and copy the data to local storage. */
1336 tmptr = gmtime (¤t) ;
1337 memcpy (&timedata, tmptr, sizeof (timedata)) ;
1338 #else
1339 tmptr = NULL ;
1340 #endif
1341
1342 if (tmptr)
1343 snprintf (str, maxlen, "%4d-%02d-%02d %02d:%02d:%02d UTC",
1344 1900 + timedata.tm_year, timedata.tm_mon, timedata.tm_mday,
1345 timedata.tm_hour, timedata.tm_min, timedata.tm_sec) ;
1346 else
1347 snprintf (str, maxlen, "Unknown date") ;
1348
1349 return ;
1350 } /* psf_get_date_str */
1351
1352 int
subformat_to_bytewidth(int format)1353 subformat_to_bytewidth (int format)
1354 {
1355 switch (format)
1356 { case SF_FORMAT_PCM_U8 :
1357 case SF_FORMAT_PCM_S8 :
1358 return 1 ;
1359 case SF_FORMAT_PCM_16 :
1360 return 2 ;
1361 case SF_FORMAT_PCM_24 :
1362 return 3 ;
1363 case SF_FORMAT_PCM_32 :
1364 case SF_FORMAT_FLOAT :
1365 return 4 ;
1366 case SF_FORMAT_DOUBLE :
1367 return 8 ;
1368 } ;
1369
1370 return 0 ;
1371 } /* subformat_to_bytewidth */
1372
1373 int
s_bitwidth_to_subformat(int bits)1374 s_bitwidth_to_subformat (int bits)
1375 { static int array [] =
1376 { SF_FORMAT_PCM_S8, SF_FORMAT_PCM_16, SF_FORMAT_PCM_24, SF_FORMAT_PCM_32
1377 } ;
1378
1379 if (bits < 8 || bits > 32)
1380 return 0 ;
1381
1382 return array [((bits + 7) / 8) - 1] ;
1383 } /* bitwidth_to_subformat */
1384
1385 int
u_bitwidth_to_subformat(int bits)1386 u_bitwidth_to_subformat (int bits)
1387 { static int array [] =
1388 { SF_FORMAT_PCM_U8, SF_FORMAT_PCM_16, SF_FORMAT_PCM_24, SF_FORMAT_PCM_32
1389 } ;
1390
1391 if (bits < 8 || bits > 32)
1392 return 0 ;
1393
1394 return array [((bits + 7) / 8) - 1] ;
1395 } /* bitwidth_to_subformat */
1396
1397 /*
1398 ** psf_rand_int32 : Not crypto quality, but more than adequate for things
1399 ** like stream serial numbers in Ogg files or the unique_id field of the
1400 ** SF_PRIVATE struct.
1401 */
1402
1403 int32_t
psf_rand_int32(void)1404 psf_rand_int32 (void)
1405 { static uint64_t value = 0 ;
1406 int k, count ;
1407
1408 if (value == 0)
1409 {
1410 #if HAVE_GETTIMEOFDAY
1411 struct timeval tv ;
1412 gettimeofday (&tv, NULL) ;
1413 value = tv.tv_sec + tv.tv_usec ;
1414 #else
1415 value = time (NULL) ;
1416 #endif
1417 } ;
1418
1419 count = 4 + (value & 7) ;
1420 for (k = 0 ; k < count ; k++)
1421 value = (11117 * value + 211231) & 0x7fffffff ;
1422
1423 return (int32_t) value ;
1424 } /* psf_rand_int32 */
1425
1426 void
append_snprintf(char * dest,size_t maxlen,const char * fmt,...)1427 append_snprintf (char * dest, size_t maxlen, const char * fmt, ...)
1428 { size_t len = strlen (dest) ;
1429
1430 if (len < maxlen)
1431 { va_list ap ;
1432
1433 va_start (ap, fmt) ;
1434 vsnprintf (dest + len, maxlen - len, fmt, ap) ;
1435 va_end (ap) ;
1436 } ;
1437
1438 return ;
1439 } /* append_snprintf */
1440
1441
1442 void
psf_strlcpy_crlf(char * dest,const char * src,size_t destmax,size_t srcmax)1443 psf_strlcpy_crlf (char *dest, const char *src, size_t destmax, size_t srcmax)
1444 { /* Must be minus 2 so it can still expand a single trailing '\n' or '\r'. */
1445 char * destend = dest + destmax - 2 ;
1446 const char * srcend = src + srcmax ;
1447
1448 while (dest < destend && src < srcend)
1449 { if ((src [0] == '\r' && src [1] == '\n') || (src [0] == '\n' && src [1] == '\r'))
1450 { *dest++ = '\r' ;
1451 *dest++ = '\n' ;
1452 src += 2 ;
1453 continue ;
1454 } ;
1455
1456 if (src [0] == '\r')
1457 { *dest++ = '\r' ;
1458 *dest++ = '\n' ;
1459 src += 1 ;
1460 continue ;
1461 } ;
1462
1463 if (src [0] == '\n')
1464 { *dest++ = '\r' ;
1465 *dest++ = '\n' ;
1466 src += 1 ;
1467 continue ;
1468 } ;
1469
1470 *dest++ = *src++ ;
1471 } ;
1472
1473 /* Make sure dest is terminated. */
1474 *dest = 0 ;
1475 } /* psf_strlcpy_crlf */
1476
1477 sf_count_t
psf_decode_frame_count(SF_PRIVATE * psf)1478 psf_decode_frame_count (SF_PRIVATE *psf)
1479 { sf_count_t count, readlen, total = 0 ;
1480 BUF_UNION ubuf ;
1481
1482 /* If we're reading from a pipe or the file is too long, just return SF_COUNT_MAX. */
1483 if (psf_is_pipe (psf) || psf->datalength > 0x1000000)
1484 return SF_COUNT_MAX ;
1485
1486 psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
1487
1488 readlen = ARRAY_LEN (ubuf.ibuf) / psf->sf.channels ;
1489 readlen *= psf->sf.channels ;
1490
1491 while ((count = psf->read_int (psf, ubuf.ibuf, readlen)) > 0)
1492 total += count ;
1493
1494 psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
1495
1496 return total / psf->sf.channels ;
1497 } /* psf_decode_frame_count */
1498
1499 /*==============================================================================
1500 */
1501
1502 #define CASE_NAME(x) case x : return #x ; break ;
1503
1504 const char *
str_of_major_format(int format)1505 str_of_major_format (int format)
1506 { switch (SF_CONTAINER (format))
1507 { CASE_NAME (SF_FORMAT_WAV) ;
1508 CASE_NAME (SF_FORMAT_AIFF) ;
1509 CASE_NAME (SF_FORMAT_AU) ;
1510 CASE_NAME (SF_FORMAT_RAW) ;
1511 CASE_NAME (SF_FORMAT_PAF) ;
1512 CASE_NAME (SF_FORMAT_SVX) ;
1513 CASE_NAME (SF_FORMAT_NIST) ;
1514 CASE_NAME (SF_FORMAT_VOC) ;
1515 CASE_NAME (SF_FORMAT_IRCAM) ;
1516 CASE_NAME (SF_FORMAT_W64) ;
1517 CASE_NAME (SF_FORMAT_MAT4) ;
1518 CASE_NAME (SF_FORMAT_MAT5) ;
1519 CASE_NAME (SF_FORMAT_PVF) ;
1520 CASE_NAME (SF_FORMAT_XI) ;
1521 CASE_NAME (SF_FORMAT_HTK) ;
1522 CASE_NAME (SF_FORMAT_SDS) ;
1523 CASE_NAME (SF_FORMAT_AVR) ;
1524 CASE_NAME (SF_FORMAT_WAVEX) ;
1525 CASE_NAME (SF_FORMAT_SD2) ;
1526 CASE_NAME (SF_FORMAT_FLAC) ;
1527 CASE_NAME (SF_FORMAT_CAF) ;
1528 CASE_NAME (SF_FORMAT_WVE) ;
1529 CASE_NAME (SF_FORMAT_OGG) ;
1530 default :
1531 break ;
1532 } ;
1533
1534 return "BAD_MAJOR_FORMAT" ;
1535 } /* str_of_major_format */
1536
1537 const char *
str_of_minor_format(int format)1538 str_of_minor_format (int format)
1539 { switch (SF_CODEC (format))
1540 { CASE_NAME (SF_FORMAT_PCM_S8) ;
1541 CASE_NAME (SF_FORMAT_PCM_16) ;
1542 CASE_NAME (SF_FORMAT_PCM_24) ;
1543 CASE_NAME (SF_FORMAT_PCM_32) ;
1544 CASE_NAME (SF_FORMAT_PCM_U8) ;
1545 CASE_NAME (SF_FORMAT_FLOAT) ;
1546 CASE_NAME (SF_FORMAT_DOUBLE) ;
1547 CASE_NAME (SF_FORMAT_ULAW) ;
1548 CASE_NAME (SF_FORMAT_ALAW) ;
1549 CASE_NAME (SF_FORMAT_IMA_ADPCM) ;
1550 CASE_NAME (SF_FORMAT_MS_ADPCM) ;
1551 CASE_NAME (SF_FORMAT_GSM610) ;
1552 CASE_NAME (SF_FORMAT_VOX_ADPCM) ;
1553 CASE_NAME (SF_FORMAT_NMS_ADPCM_16) ;
1554 CASE_NAME (SF_FORMAT_NMS_ADPCM_24) ;
1555 CASE_NAME (SF_FORMAT_NMS_ADPCM_32) ;
1556 CASE_NAME (SF_FORMAT_G721_32) ;
1557 CASE_NAME (SF_FORMAT_G723_24) ;
1558 CASE_NAME (SF_FORMAT_G723_40) ;
1559 CASE_NAME (SF_FORMAT_DWVW_12) ;
1560 CASE_NAME (SF_FORMAT_DWVW_16) ;
1561 CASE_NAME (SF_FORMAT_DWVW_24) ;
1562 CASE_NAME (SF_FORMAT_DWVW_N) ;
1563 CASE_NAME (SF_FORMAT_DPCM_8) ;
1564 CASE_NAME (SF_FORMAT_DPCM_16) ;
1565 CASE_NAME (SF_FORMAT_VORBIS) ;
1566 default :
1567 break ;
1568 } ;
1569
1570 return "BAD_MINOR_FORMAT" ;
1571 } /* str_of_minor_format */
1572
1573 const char *
str_of_open_mode(int mode)1574 str_of_open_mode (int mode)
1575 { switch (mode)
1576 { CASE_NAME (SFM_READ) ;
1577 CASE_NAME (SFM_WRITE) ;
1578 CASE_NAME (SFM_RDWR) ;
1579
1580 default :
1581 break ;
1582 } ;
1583
1584 return "BAD_MODE" ;
1585 } /* str_of_open_mode */
1586
1587 const char *
str_of_endianness(int end)1588 str_of_endianness (int end)
1589 { switch (end)
1590 { CASE_NAME (SF_ENDIAN_BIG) ;
1591 CASE_NAME (SF_ENDIAN_LITTLE) ;
1592 CASE_NAME (SF_ENDIAN_CPU) ;
1593 default :
1594 break ;
1595 } ;
1596
1597 /* Zero length string for SF_ENDIAN_FILE. */
1598 return "" ;
1599 } /* str_of_endianness */
1600
1601 /*==============================================================================
1602 */
1603
1604 void
psf_f2s_array(const float * src,short * dest,int count,int normalize)1605 psf_f2s_array (const float *src, short *dest, int count, int normalize)
1606 { float normfact ;
1607
1608 normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ;
1609 while (--count >= 0)
1610 dest [count] = psf_lrintf (src [count] * normfact) ;
1611
1612 return ;
1613 } /* psf_f2s_array */
1614
1615 void
psf_f2s_clip_array(const float * src,short * dest,int count,int normalize)1616 psf_f2s_clip_array (const float *src, short *dest, int count, int normalize)
1617 { float normfact, scaled_value ;
1618
1619 normfact = normalize ? (1.0 * 0x8000) : 1.0 ;
1620
1621 while (--count >= 0)
1622 { scaled_value = src [count] * normfact ;
1623 if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFF))
1624 { dest [count] = 0x7FFF ;
1625 continue ;
1626 } ;
1627 if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x1000))
1628 { dest [count] = 0x8000 ;
1629 continue ;
1630 } ;
1631
1632 dest [count] = psf_lrintf (scaled_value) ;
1633 } ;
1634
1635 return ;
1636 } /* psf_f2s_clip_array */
1637
1638 void
psf_d2s_array(const double * src,short * dest,int count,int normalize)1639 psf_d2s_array (const double *src, short *dest, int count, int normalize)
1640 { double normfact ;
1641
1642 normfact = normalize ? (1.0 * 0x7FFF) : 1.0 ;
1643 while (--count >= 0)
1644 dest [count] = psf_lrint (src [count] * normfact) ;
1645
1646 return ;
1647 } /* psf_f2s_array */
1648
1649 void
psf_d2s_clip_array(const double * src,short * dest,int count,int normalize)1650 psf_d2s_clip_array (const double *src, short *dest, int count, int normalize)
1651 { double normfact, scaled_value ;
1652
1653 normfact = normalize ? (1.0 * 0x8000) : 1.0 ;
1654
1655 while (--count >= 0)
1656 { scaled_value = src [count] * normfact ;
1657 if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFF))
1658 { dest [count] = 0x7FFF ;
1659 continue ;
1660 } ;
1661 if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x1000))
1662 { dest [count] = 0x8000 ;
1663 continue ;
1664 } ;
1665
1666 dest [count] = psf_lrint (scaled_value) ;
1667 } ;
1668
1669 return ;
1670 } /* psf_d2s_clip_array */
1671
1672
1673 void
psf_f2i_array(const float * src,int * dest,int count,int normalize)1674 psf_f2i_array (const float *src, int *dest, int count, int normalize)
1675 { float normfact ;
1676
1677 normfact = normalize ? (1.0 * 0x7FFFFFFF) : 1.0 ;
1678 while (--count >= 0)
1679 dest [count] = psf_lrintf (src [count] * normfact) ;
1680
1681 return ;
1682 } /* psf_f2i_array */
1683
1684 void
psf_f2i_clip_array(const float * src,int * dest,int count,int normalize)1685 psf_f2i_clip_array (const float *src, int *dest, int count, int normalize)
1686 { float normfact, scaled_value ;
1687
1688 normfact = normalize ? (8.0 * 0x10000000) : 1.0 ;
1689
1690 while (--count >= 0)
1691 { scaled_value = src [count] * normfact ;
1692 if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF))
1693 { dest [count] = 0x7FFFFFFF ;
1694 continue ;
1695 } ;
1696 if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000))
1697 { dest [count] = 0x80000000 ;
1698 continue ;
1699 } ;
1700
1701 dest [count] = psf_lrintf (scaled_value) ;
1702 } ;
1703
1704 return ;
1705 } /* psf_f2i_clip_array */
1706
1707 void
psf_d2i_array(const double * src,int * dest,int count,int normalize)1708 psf_d2i_array (const double *src, int *dest, int count, int normalize)
1709 { double normfact ;
1710
1711 normfact = normalize ? (1.0 * 0x7FFFFFFF) : 1.0 ;
1712 while (--count >= 0)
1713 dest [count] = psf_lrint (src [count] * normfact) ;
1714
1715 return ;
1716 } /* psf_f2i_array */
1717
1718 void
psf_d2i_clip_array(const double * src,int * dest,int count,int normalize)1719 psf_d2i_clip_array (const double *src, int *dest, int count, int normalize)
1720 { double normfact, scaled_value ;
1721
1722 normfact = normalize ? (8.0 * 0x10000000) : 1.0 ;
1723
1724 while (--count >= 0)
1725 { scaled_value = src [count] * normfact ;
1726 if (CPU_CLIPS_POSITIVE == 0 && scaled_value >= (1.0 * 0x7FFFFFFF))
1727 { dest [count] = 0x7FFFFFFF ;
1728 continue ;
1729 } ;
1730 if (CPU_CLIPS_NEGATIVE == 0 && scaled_value <= (-8.0 * 0x10000000))
1731 { dest [count] = 0x80000000 ;
1732 continue ;
1733 } ;
1734
1735 dest [count] = psf_lrint (scaled_value) ;
1736 } ;
1737
1738 return ;
1739 } /* psf_d2i_clip_array */
1740
1741 FILE *
psf_open_tmpfile(char * fname,size_t fnamelen)1742 psf_open_tmpfile (char * fname, size_t fnamelen)
1743 { const char * tmpdir ;
1744 FILE * file ;
1745
1746 if (OS_IS_WIN32)
1747 tmpdir = getenv ("TEMP") ;
1748 else
1749 { tmpdir = getenv ("TMPDIR") ;
1750 tmpdir = tmpdir == NULL ? "/tmp" : tmpdir ;
1751 } ;
1752
1753 if (tmpdir && access (tmpdir, R_OK | W_OK | X_OK) == 0)
1754 { snprintf (fname, fnamelen, "%s/%x%x-alac.tmp", tmpdir, psf_rand_int32 (), psf_rand_int32 ()) ;
1755 if ((file = fopen (fname, "wb+")) != NULL)
1756 return file ;
1757 } ;
1758
1759 snprintf (fname, fnamelen, "%x%x-alac.tmp", psf_rand_int32 (), psf_rand_int32 ()) ;
1760 if ((file = fopen (fname, "wb+")) != NULL)
1761 return file ;
1762
1763 memset (fname, 0, fnamelen) ;
1764 return NULL ;
1765 } /* psf_open_tmpfile */
1766