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 	audiofile.c
24 
25 	This file implements many of the main interface routines of the
26 	Audio File Library.
27 */
28 
29 #include "config.h"
30 
31 #include <assert.h>
32 #include <stdint.h>
33 #include <stdlib.h>
34 #include <string.h>
35 
36 #include "FileHandle.h"
37 #include "Setup.h"
38 #include "Track.h"
39 #include "afinternal.h"
40 #include "audiofile.h"
41 #include "modules/Module.h"
42 #include "modules/ModuleState.h"
43 #include "units.h"
44 #include "util.h"
45 
afGetDataOffset(AFfilehandle file,int trackid)46 AFfileoffset afGetDataOffset (AFfilehandle file, int trackid)
47 {
48 	if (!_af_filehandle_ok(file))
49 		return -1;
50 
51 	Track *track = file->getTrack(trackid);
52 	if (!track)
53 		return -1;
54 
55 	return track->fpos_first_frame;
56 }
57 
afGetTrackBytes(AFfilehandle file,int trackid)58 AFfileoffset afGetTrackBytes (AFfilehandle file, int trackid)
59 {
60 	if (!_af_filehandle_ok(file))
61 		return -1;
62 
63 	Track *track = file->getTrack(trackid);
64 	if (!track)
65 		return -1;
66 
67 	return track->data_size;
68 }
69 
70 /*
71 	afGetFrameSize returns the size (in bytes) of a sample frame from
72 	the specified track of an audio file.
73 
74 	stretch3to4 == true: size which user sees
75 	stretch3to4 == false: size used in file
76 */
afGetFrameSize(AFfilehandle file,int trackid,int stretch3to4)77 float afGetFrameSize (AFfilehandle file, int trackid, int stretch3to4)
78 {
79 	if (!_af_filehandle_ok(file))
80 		return -1;
81 
82 	Track *track = file->getTrack(trackid);
83 	if (!track)
84 		return -1;
85 
86 	return _af_format_frame_size(&track->f, stretch3to4);
87 }
88 
afGetVirtualFrameSize(AFfilehandle file,int trackid,int stretch3to4)89 float afGetVirtualFrameSize (AFfilehandle file, int trackid, int stretch3to4)
90 {
91 	if (!_af_filehandle_ok(file))
92 		return -1;
93 
94 	Track *track = file->getTrack(trackid);
95 	if (!track)
96 		return -1;
97 
98 	return _af_format_frame_size(&track->v, stretch3to4);
99 }
100 
afSeekFrame(AFfilehandle file,int trackid,AFframecount frame)101 AFframecount afSeekFrame (AFfilehandle file, int trackid, AFframecount frame)
102 {
103 	if (!_af_filehandle_ok(file))
104 		return -1;
105 
106 	if (!file->checkCanRead())
107 		return -1;
108 
109 	Track *track = file->getTrack(trackid);
110 	if (!track)
111 		return -1;
112 
113 	if (track->ms->isDirty() && track->ms->setup(file, track) == AF_FAIL)
114 		return -1;
115 
116 	if (frame < 0)
117 		return track->nextvframe;
118 
119 	/* Optimize the case of seeking to the current position. */
120 	if (frame == track->nextvframe)
121 		return track->nextvframe;
122 
123 	/* Limit request to the number of frames in the file. */
124 	if (track->totalvframes != -1)
125 		if (frame > track->totalvframes)
126 			frame = track->totalvframes - 1;
127 
128 	/*
129 		Now that the modules are not dirty and frame
130 		represents a valid virtual frame, we call
131 		_AFsetupmodules again after setting track->nextvframe.
132 
133 		_AFsetupmodules will look at track->nextvframe and
134 		compute track->nextfframe in clever and mysterious
135 		ways.
136 	*/
137 	track->nextvframe = frame;
138 
139 	if (track->ms->setup(file, track) == AF_FAIL)
140 		return -1;
141 
142 	return track->nextvframe;
143 }
144 
afTellFrame(AFfilehandle file,int trackid)145 AFfileoffset afTellFrame (AFfilehandle file, int trackid)
146 {
147 	return afSeekFrame(file, trackid, -1);
148 }
149 
afSetVirtualByteOrder(AFfilehandle file,int trackid,int byteorder)150 int afSetVirtualByteOrder (AFfilehandle file, int trackid, int byteorder)
151 {
152 	if (!_af_filehandle_ok(file))
153 		return AF_FAIL;
154 
155 	Track *track = file->getTrack(trackid);
156 	if (!track)
157 		return AF_FAIL;
158 
159 	if (byteorder != AF_BYTEORDER_BIGENDIAN &&
160 		byteorder != AF_BYTEORDER_LITTLEENDIAN)
161 	{
162 		_af_error(AF_BAD_BYTEORDER, "invalid byte order %d", byteorder);
163 		return AF_FAIL;
164 	}
165 
166 	track->v.byteOrder = byteorder;
167 	track->ms->setDirty();
168 
169 	return AF_SUCCEED;
170 }
171 
afGetByteOrder(AFfilehandle file,int trackid)172 int afGetByteOrder (AFfilehandle file, int trackid)
173 {
174 	if (!_af_filehandle_ok(file))
175 		return -1;
176 
177 	Track *track = file->getTrack(trackid);
178 	if (!track)
179 		return -1;
180 
181 	return track->f.byteOrder;
182 }
183 
afGetVirtualByteOrder(AFfilehandle file,int trackid)184 int afGetVirtualByteOrder (AFfilehandle file, int trackid)
185 {
186 	if (!_af_filehandle_ok(file))
187 		return -1;
188 
189 	Track *track = file->getTrack(trackid);
190 	if (!track)
191 		return -1;
192 
193 	return track->v.byteOrder;
194 }
195 
afGetFrameCount(AFfilehandle file,int trackid)196 AFframecount afGetFrameCount (AFfilehandle file, int trackid)
197 {
198 	if (!_af_filehandle_ok(file))
199 		return -1;
200 
201 	Track *track = file->getTrack(trackid);
202 	if (!track)
203 		return -1;
204 
205 	if (track->ms->isDirty() && track->ms->setup(file, track) == AF_FAIL)
206 		return -1;
207 
208 	return track->totalvframes;
209 }
210 
afGetRate(AFfilehandle file,int trackid)211 double afGetRate (AFfilehandle file, int trackid)
212 {
213 	if (!_af_filehandle_ok(file))
214 		return -1;
215 
216 	Track *track = file->getTrack(trackid);
217 	if (!track)
218 		return -1;
219 
220 	return track->f.sampleRate;
221 }
222 
afGetChannels(AFfilehandle file,int trackid)223 int afGetChannels (AFfilehandle file, int trackid)
224 {
225 	if (!_af_filehandle_ok(file))
226 		return -1;
227 
228 	Track *track = file->getTrack(trackid);
229 	if (!track)
230 		return -1;
231 
232 	return track->f.channelCount;
233 }
234 
afGetSampleFormat(AFfilehandle file,int trackid,int * sampleFormat,int * sampleWidth)235 void afGetSampleFormat (AFfilehandle file, int trackid, int *sampleFormat, int *sampleWidth)
236 {
237 	if (!_af_filehandle_ok(file))
238 		return;
239 
240 	Track *track = file->getTrack(trackid);
241 	if (!track)
242 		return;
243 
244 	if (sampleFormat)
245 		*sampleFormat = track->f.sampleFormat;
246 
247 	if (sampleWidth)
248 		*sampleWidth = track->f.sampleWidth;
249 }
250 
afGetVirtualSampleFormat(AFfilehandle file,int trackid,int * sampleFormat,int * sampleWidth)251 void afGetVirtualSampleFormat (AFfilehandle file, int trackid, int *sampleFormat, int *sampleWidth)
252 {
253 	if (!_af_filehandle_ok(file))
254 		return;
255 
256 	Track *track = file->getTrack(trackid);
257 	if (!track)
258 		return;
259 
260 	if (sampleFormat)
261 		*sampleFormat = track->v.sampleFormat;
262 
263 	if (sampleWidth)
264 		*sampleWidth = track->v.sampleWidth;
265 }
266 
afSetVirtualSampleFormat(AFfilehandle file,int trackid,int sampleFormat,int sampleWidth)267 int afSetVirtualSampleFormat (AFfilehandle file, int trackid,
268 	int sampleFormat, int sampleWidth)
269 {
270 	if (!_af_filehandle_ok(file))
271 		return -1;
272 
273 	Track *track = file->getTrack(trackid);
274 	if (!track)
275 		return -1;
276 
277 	if (_af_set_sample_format(&track->v, sampleFormat, sampleWidth) == AF_FAIL)
278 		return -1;
279 
280 	track->ms->setDirty();
281 
282 	return 0;
283 }
284 
285 /* XXXmpruett fix the version */
afGetFileFormat(AFfilehandle file,int * version)286 int afGetFileFormat (AFfilehandle file, int *version)
287 {
288 	if (!_af_filehandle_ok(file))
289 		return -1;
290 
291 	if (version != NULL)
292 		*version = file->getVersion();
293 
294 	return file->m_fileFormat;
295 }
296 
afSetVirtualChannels(AFfilehandle file,int trackid,int channelCount)297 int afSetVirtualChannels (AFfilehandle file, int trackid, int channelCount)
298 {
299 	if (!_af_filehandle_ok(file))
300 		return -1;
301 
302 	Track *track = file->getTrack(trackid);
303 	if (!track)
304 		return -1;
305 
306 	track->v.channelCount = channelCount;
307 	track->ms->setDirty();
308 
309 	if (track->channelMatrix)
310 		free(track->channelMatrix);
311 	track->channelMatrix = NULL;
312 
313 	return 0;
314 }
315 
afGetVirtualRate(AFfilehandle file,int trackid)316 double afGetVirtualRate (AFfilehandle file, int trackid)
317 {
318 	if (!_af_filehandle_ok(file))
319 		return -1;
320 
321 	Track *track = file->getTrack(trackid);
322 	if (!track)
323 		return -1;
324 
325 	return track->v.sampleRate;
326 }
327 
afSetVirtualRate(AFfilehandle file,int trackid,double rate)328 int afSetVirtualRate (AFfilehandle file, int trackid, double rate)
329 {
330 	if (!_af_filehandle_ok(file))
331 		return -1;
332 
333 	Track *track = file->getTrack(trackid);
334 	if (!track)
335 		return -1;
336 
337 	if (rate < 0)
338 	{
339 		_af_error(AF_BAD_RATE, "invalid sampling rate %.30g", rate);
340 		return -1;
341 	}
342 
343 	track->v.sampleRate = rate;
344 	track->ms->setDirty();
345 
346 	return 0;
347 }
348 
afSetChannelMatrix(AFfilehandle file,int trackid,double * matrix)349 void afSetChannelMatrix (AFfilehandle file, int trackid, double* matrix)
350 {
351 	if (!_af_filehandle_ok(file))
352 		return;
353 
354 	Track *track = file->getTrack(trackid);
355 	if (!track)
356 		return;
357 
358 	if (track->channelMatrix != NULL)
359 		free(track->channelMatrix);
360 	track->channelMatrix = NULL;
361 
362 	if (matrix != NULL)
363 	{
364 		int	i, size;
365 
366 		size = track->v.channelCount * track->f.channelCount;
367 
368 		track->channelMatrix = (double *) malloc(size * sizeof (double));
369 
370 		for (i = 0; i < size; i++)
371 			track->channelMatrix[i] = matrix[i];
372 	}
373 }
374 
afGetVirtualChannels(AFfilehandle file,int trackid)375 int afGetVirtualChannels (AFfilehandle file, int trackid)
376 {
377 	if (!_af_filehandle_ok(file))
378 		return -1;
379 
380 	Track *track = file->getTrack(trackid);
381 	if (!track)
382 		return -1;
383 
384 	return track->v.channelCount;
385 }
386