• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 (&current) ;
1330 
1331 #if defined (HAVE_GMTIME_R)
1332 	/* If the re-entrant version is available, use it. */
1333 	tmptr = gmtime_r (&current, &timedata) ;
1334 #elif defined (HAVE_GMTIME)
1335 	/* Otherwise use the standard one and copy the data to local storage. */
1336 	tmptr = gmtime (&current) ;
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