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