1 /*
2 	Audio File Library
3 	Copyright (C) 1998-2000, Michael Pruett <michael@68k.org>
4 	Copyright (C) 2000, Silicon Graphics, Inc.
5 
6 	This library is free software; you can redistribute it and/or
7 	modify it under the terms of the GNU Lesser General Public
8 	License as published by the Free Software Foundation; either
9 	version 2.1 of the License, or (at your option) any later version.
10 
11 	This library is distributed in the hope that it will be useful,
12 	but WITHOUT ANY WARRANTY; without even the implied warranty of
13 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 	Lesser General Public License for more details.
15 
16 	You should have received a copy of the GNU Lesser General Public
17 	License along with this library; if not, write to the
18 	Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 	Boston, MA  02110-1301  USA
20 */
21 
22 /*
23 	util.c
24 
25 	This file contains general utility routines for the Audio File
26 	Library.
27 */
28 
29 #include "config.h"
30 
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <string.h>
34 #include <assert.h>
35 
36 #include "audiofile.h"
37 #include "aupvlist.h"
38 
39 #include "AudioFormat.h"
40 #include "File.h"
41 #include "FileHandle.h"
42 #include "Setup.h"
43 #include "Track.h"
44 #include "afinternal.h"
45 #include "aupvinternal.h"
46 #include "byteorder.h"
47 #include "compression.h"
48 #include "pcm.h"
49 #include "units.h"
50 #include "util.h"
51 
52 /*
53 	_af_filesetup_ok and _af_filehandle_ok are sanity check routines
54 	which are called at the beginning of every external subroutine.
55 */
_af_filesetup_ok(AFfilesetup setup)56 bool _af_filesetup_ok (AFfilesetup setup)
57 {
58 	if (setup == AF_NULL_FILESETUP)
59 	{
60 		_af_error(AF_BAD_FILESETUP, "null file setup");
61 		return false;
62 	}
63 	if (setup->valid != _AF_VALID_FILESETUP)
64 	{
65 		_af_error(AF_BAD_FILESETUP, "invalid file setup");
66 		return false;
67 	}
68 	return true;
69 }
70 
_af_filehandle_ok(AFfilehandle file)71 bool _af_filehandle_ok (AFfilehandle file)
72 {
73 	if (file == AF_NULL_FILEHANDLE)
74 	{
75 		_af_error(AF_BAD_FILEHANDLE, "null file handle");
76 		return false;
77 	}
78 	if (file->m_valid != _AF_VALID_FILEHANDLE)
79 	{
80 		_af_error(AF_BAD_FILEHANDLE, "invalid file handle");
81 		return false;
82 	}
83 	return true;
84 }
85 
_af_malloc(size_t size)86 void *_af_malloc (size_t size)
87 {
88 	void	*p;
89 
90 	if (size <= 0)
91 	{
92 		_af_error(AF_BAD_MALLOC, "bad memory allocation size request %zd", size);
93 		return NULL;
94 	}
95 
96 	p = malloc(size);
97 
98 #ifdef AF_DEBUG
99 	if (p)
100 		memset(p, 0xff, size);
101 #endif
102 
103 	if (p == NULL)
104 	{
105 		_af_error(AF_BAD_MALLOC, "allocation of %zd bytes failed", size);
106 		return NULL;
107 	}
108 
109 	return p;
110 }
111 
_af_strdup(const char * s)112 char *_af_strdup (const char *s)
113 {
114 	char *p = (char *) malloc(strlen(s) + 1);
115 
116 	if (p)
117 		strcpy(p, s);
118 
119 	return p;
120 }
121 
_af_realloc(void * p,size_t size)122 void *_af_realloc (void *p, size_t size)
123 {
124 	if (size <= 0)
125 	{
126 		_af_error(AF_BAD_MALLOC, "bad memory allocation size request %zd", size);
127 		return NULL;
128 	}
129 
130 	p = realloc(p, size);
131 
132 	if (p == NULL)
133 	{
134 		_af_error(AF_BAD_MALLOC, "allocation of %zd bytes failed", size);
135 		return NULL;
136 	}
137 
138 	return p;
139 }
140 
_af_calloc(size_t nmemb,size_t size)141 void *_af_calloc (size_t nmemb, size_t size)
142 {
143 	void	*p;
144 
145 	if (nmemb <= 0 || size <= 0)
146 	{
147 		_af_error(AF_BAD_MALLOC, "bad memory allocation size request "
148 			"%zd elements of %zd bytes each", nmemb, size);
149 		return NULL;
150 	}
151 
152 	p = calloc(nmemb, size);
153 
154 	if (p == NULL)
155 	{
156 		_af_error(AF_BAD_MALLOC, "allocation of %zd bytes failed",
157 			nmemb*size);
158 		return NULL;
159 	}
160 
161 	return p;
162 }
163 
_af_pv_long(long val)164 AUpvlist _af_pv_long (long val)
165 {
166 	AUpvlist	ret = AUpvnew(1);
167 	AUpvsetparam(ret, 0, 0);
168 	AUpvsetvaltype(ret, 0, AU_PVTYPE_LONG);
169 	AUpvsetval(ret, 0, &val);
170 	return ret;
171 }
172 
_af_pv_double(double val)173 AUpvlist _af_pv_double (double val)
174 {
175 	AUpvlist	ret = AUpvnew(1);
176 	AUpvsetparam(ret, 0, 0);
177 	AUpvsetvaltype(ret, 0, AU_PVTYPE_DOUBLE);
178 	AUpvsetval(ret, 0, &val);
179 	return ret;
180 }
181 
_af_pv_pointer(void * val)182 AUpvlist _af_pv_pointer (void *val)
183 {
184 	AUpvlist	ret = AUpvnew(1);
185 	AUpvsetparam(ret, 0, 0);
186 	AUpvsetvaltype(ret, 0, AU_PVTYPE_PTR);
187 	AUpvsetval(ret, 0, &val);
188 	return ret;
189 }
190 
_af_pv_getlong(AUpvlist pvlist,int param,long * l)191 bool _af_pv_getlong (AUpvlist pvlist, int param, long *l)
192 {
193 	for (int i=0; i<AUpvgetmaxitems(pvlist); i++)
194 	{
195 		int	p, t;
196 
197 		AUpvgetparam(pvlist, i, &p);
198 
199 		if (p != param)
200 			continue;
201 
202 		AUpvgetvaltype(pvlist, i, &t);
203 
204 		/* Ensure that this parameter is of type AU_PVTYPE_LONG. */
205 		if (t != AU_PVTYPE_LONG)
206 			return false;
207 
208 		AUpvgetval(pvlist, i, l);
209 		return true;
210 	}
211 
212 	return false;
213 }
214 
_af_pv_getdouble(AUpvlist pvlist,int param,double * d)215 bool _af_pv_getdouble (AUpvlist pvlist, int param, double *d)
216 {
217 	for (int i=0; i<AUpvgetmaxitems(pvlist); i++)
218 	{
219 		int	p, t;
220 
221 		AUpvgetparam(pvlist, i, &p);
222 
223 		if (p != param)
224 			continue;
225 
226 		AUpvgetvaltype(pvlist, i, &t);
227 
228 		/* Ensure that this parameter is of type AU_PVTYPE_DOUBLE. */
229 		if (t != AU_PVTYPE_DOUBLE)
230 			return false;
231 
232 		AUpvgetval(pvlist, i, d);
233 		return true;
234 	}
235 
236 	return false;
237 }
238 
_af_pv_getptr(AUpvlist pvlist,int param,void ** v)239 bool _af_pv_getptr (AUpvlist pvlist, int param, void **v)
240 {
241 	for (int i=0; i<AUpvgetmaxitems(pvlist); i++)
242 	{
243 		int	p, t;
244 
245 		AUpvgetparam(pvlist, i, &p);
246 
247 		if (p != param)
248 			continue;
249 
250 		AUpvgetvaltype(pvlist, i, &t);
251 
252 		/* Ensure that this parameter is of type AU_PVTYPE_PTR. */
253 		if (t != AU_PVTYPE_PTR)
254 			return false;
255 
256 		AUpvgetval(pvlist, i, v);
257 		return true;
258 	}
259 
260 	return false;
261 }
262 
_af_format_sample_size_uncompressed(const AudioFormat * format,bool stretch3to4)263 int _af_format_sample_size_uncompressed (const AudioFormat *format, bool stretch3to4)
264 {
265 	int	size = 0;
266 
267 	switch (format->sampleFormat)
268 	{
269 		case AF_SAMPFMT_FLOAT:
270 			size = sizeof (float);
271 			break;
272 		case AF_SAMPFMT_DOUBLE:
273 			size = sizeof (double);
274 			break;
275 		default:
276 			size = (int) (format->sampleWidth + 7) / 8;
277 			if (format->compressionType == AF_COMPRESSION_NONE &&
278 				size == 3 && stretch3to4)
279 				size = 4;
280 			break;
281 	}
282 
283 	return size;
284 }
285 
_af_format_sample_size(const AudioFormat * fmt,bool stretch3to4)286 float _af_format_sample_size (const AudioFormat *fmt, bool stretch3to4)
287 {
288 	const CompressionUnit *unit = _af_compression_unit_from_id(fmt->compressionType);
289 	float squishFactor = unit->squishFactor;
290 
291 	return _af_format_sample_size_uncompressed(fmt, stretch3to4) /
292 		squishFactor;
293 }
294 
_af_format_frame_size_uncompressed(const AudioFormat * fmt,bool stretch3to4)295 int _af_format_frame_size_uncompressed (const AudioFormat *fmt, bool stretch3to4)
296 {
297 	return _af_format_sample_size_uncompressed(fmt, stretch3to4) *
298 		fmt->channelCount;
299 }
300 
_af_format_frame_size(const AudioFormat * fmt,bool stretch3to4)301 float _af_format_frame_size (const AudioFormat *fmt, bool stretch3to4)
302 {
303 	const CompressionUnit *unit = _af_compression_unit_from_id(fmt->compressionType);
304 	float squishFactor = unit->squishFactor;
305 
306 	return _af_format_frame_size_uncompressed(fmt, stretch3to4) /
307 		squishFactor;
308 }
309 
310 /*
311 	Set the sampleFormat and sampleWidth fields in f, and set the
312 	PCM info to the appropriate default values for the given sample
313 	format and sample width.
314 */
_af_set_sample_format(AudioFormat * f,int sampleFormat,int sampleWidth)315 status _af_set_sample_format (AudioFormat *f, int sampleFormat, int sampleWidth)
316 {
317 	switch (sampleFormat)
318 	{
319 		case AF_SAMPFMT_UNSIGNED:
320 		case AF_SAMPFMT_TWOSCOMP:
321 		if (sampleWidth < 1 || sampleWidth > 32)
322 		{
323 			_af_error(AF_BAD_SAMPFMT,
324 				"illegal sample width %d for integer data",
325 				sampleWidth);
326 			return AF_FAIL;
327 		}
328 		else
329 		{
330 			int bytes;
331 
332 			f->sampleFormat = sampleFormat;
333 			f->sampleWidth = sampleWidth;
334 
335 			bytes = _af_format_sample_size_uncompressed(f, false);
336 
337 			if (sampleFormat == AF_SAMPFMT_TWOSCOMP)
338 				f->pcm = _af_default_signed_integer_pcm_mappings[bytes];
339 			else
340 				f->pcm = _af_default_unsigned_integer_pcm_mappings[bytes];
341 		}
342 		break;
343 
344 		case AF_SAMPFMT_FLOAT:
345 			f->sampleFormat = sampleFormat;
346 			f->sampleWidth = 32;
347 			f->pcm = _af_default_float_pcm_mapping;
348 			break;
349 		case AF_SAMPFMT_DOUBLE:
350 			f->sampleFormat = sampleFormat;
351 			f->sampleWidth = 64;      /*for convenience */
352 			f->pcm = _af_default_double_pcm_mapping;
353 			break;
354 		default:
355 			_af_error(AF_BAD_SAMPFMT, "unknown sample format %d",
356 				sampleFormat);
357 			return AF_FAIL;
358 	}
359 
360 	return AF_SUCCEED;
361 }
362 
363 /*
364 	Verify the uniqueness of the nids ids given.
365 
366 	idname is the name of what the ids identify, as in "loop"
367 	iderr is an error as in AF_BAD_LOOPID
368 */
_af_unique_ids(const int * ids,int nids,const char * idname,int iderr)369 bool _af_unique_ids (const int *ids, int nids, const char *idname, int iderr)
370 {
371 	for (int i = 0; i < nids; i++)
372 	{
373 		for (int j = 0; j < i; j++)
374 		{
375 			if (ids[i] == ids[j])
376 			{
377 				_af_error(iderr, "nonunique %s id %d", idname, ids[i]);
378 				return false;
379 			}
380 		}
381 	}
382 
383 	return true;
384 }
385