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