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