/* Audio File Library Copyright (C) 1998-2000, Michael Pruett Copyright (C) 2000, Silicon Graphics, Inc. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307 USA. */ /* audiofile.c This file implements many of the main interface routines of the Audio File Library. */ #ifdef HAVE_CONFIG_H #include #endif #include #include #include #include #include #include "audiofile.h" #include "util.h" #include "afinternal.h" #include "afinternal.h" #include "units.h" #include "modules.h" extern _Unit _af_units[]; AFfileoffset afGetDataOffset (AFfilehandle file, int trackid) { _Track *track; if (!_af_filehandle_ok(file)) return -1; if ((track = _af_filehandle_get_track(file, trackid)) == NULL) return -1; return track->fpos_first_frame; } AFfileoffset afGetTrackBytes (AFfilehandle file, int trackid) { _Track *track; if (!_af_filehandle_ok(file)) return -1; track = _af_filehandle_get_track(file, trackid); return track->data_size; } /* afGetFrameSize returns the size (in bytes) of a sample frame from the specified track of an audio file. stretch3to4 == AF_TRUE: size which user sees stretch3to4 == AF_FALSE: size used in file */ float afGetFrameSize (AFfilehandle file, int trackid, int stretch3to4) { _Track *track; if (!_af_filehandle_ok(file)) return -1; if ((track = _af_filehandle_get_track(file, trackid)) == NULL) return -1; return _af_format_frame_size(&track->f, stretch3to4); } float afGetVirtualFrameSize (AFfilehandle file, int trackid, int stretch3to4) { _Track *track; if (!_af_filehandle_ok(file)) return -1; if ((track = _af_filehandle_get_track(file, trackid)) == NULL) return -1; return _af_format_frame_size(&track->v, stretch3to4); } AFframecount afSeekFrame (AFfilehandle file, int trackid, AFframecount frame) { _Track *track; if (!_af_filehandle_ok(file)) return -1; if (!_af_filehandle_can_read(file)) return -1; if ((track = _af_filehandle_get_track(file, trackid)) == NULL) return -1; if (track->ms.modulesdirty) if (_AFsetupmodules(file, track) != AF_SUCCEED) return -1; if (frame < 0) return track->nextvframe; /* Optimize the case of seeking to the current position. */ if (frame == track->nextvframe) return track->nextvframe; /* Limit request to the number of frames in the file. */ if (track->totalvframes != -1) if (frame > track->totalvframes) frame = track->totalvframes - 1; /* Now that the modules are not dirty and frame represents a valid virtual frame, we call _AFsetupmodules again after setting track->nextvframe. _AFsetupmodules will look at track->nextvframe and compute track->nextfframe in clever and mysterious ways. */ track->nextvframe = frame; if (_AFsetupmodules(file, track) != AF_SUCCEED) return -1; return track->nextvframe; } AFfileoffset afTellFrame (AFfilehandle file, int trackid) { return afSeekFrame(file, trackid, -1); } int afSetVirtualByteOrder (AFfilehandle handle, int track, int byteorder) { _Track *currentTrack; if (!_af_filehandle_ok(handle)) return -1; if (NULL == (currentTrack = _af_filehandle_get_track(handle, track))) return AF_FAIL; if (byteorder != AF_BYTEORDER_BIGENDIAN && byteorder != AF_BYTEORDER_LITTLEENDIAN) { _af_error(AF_BAD_BYTEORDER, "invalid byte order %d", byteorder); return AF_FAIL; } currentTrack->v.byteOrder = byteorder; currentTrack->ms.modulesdirty = AF_TRUE; return AF_SUCCEED; } int afGetByteOrder (AFfilehandle handle, int track) { _Track *currentTrack; if (!_af_filehandle_ok(handle)) return -1; if ((currentTrack = _af_filehandle_get_track(handle, track)) == NULL) return -1; return (currentTrack->f.byteOrder); } int afGetVirtualByteOrder (AFfilehandle handle, int track) { _Track *currentTrack; if (!_af_filehandle_ok(handle)) return -1; if ((currentTrack = _af_filehandle_get_track(handle, track)) == NULL) return -1; return (currentTrack->v.byteOrder); } AFframecount afGetFrameCount (AFfilehandle file, int trackid) { _Track *track; if (!_af_filehandle_ok(file)) return -1; if ((track = _af_filehandle_get_track(file, trackid)) == NULL) return -1; if (track->ms.modulesdirty) { if (_AFsetupmodules(file, track) != AF_SUCCEED) return -1; } return track->totalvframes; } double afGetRate (AFfilehandle file, int trackid) { _Track *track; if ((track = _af_filehandle_get_track(file, trackid)) == NULL) return -1; return track->f.sampleRate; } int afGetChannels (AFfilehandle file, int trackid) { _Track *track; if ((track = _af_filehandle_get_track(file, trackid)) == NULL) return -1; return track->f.channelCount; } void afGetSampleFormat (AFfilehandle file, int trackid, int *sampleFormat, int *sampleWidth) { _Track *track; if ((track = _af_filehandle_get_track(file, trackid)) == NULL) return; if (sampleFormat != NULL) *sampleFormat = track->f.sampleFormat; if (sampleFormat != NULL) *sampleWidth = track->f.sampleWidth; } void afGetVirtualSampleFormat (AFfilehandle file, int trackid, int *sampleFormat, int *sampleWidth) { _Track *track; if ((track = _af_filehandle_get_track(file, trackid)) == NULL) return; if (sampleFormat != NULL) *sampleFormat = track->v.sampleFormat; if (sampleFormat != NULL) *sampleWidth = track->v.sampleWidth; } int afSetVirtualSampleFormat (AFfilehandle file, int trackid, int sampleFormat, int sampleWidth) { _Track *track; if (!_af_filehandle_ok(file)) return -1; if ((track = _af_filehandle_get_track(file, trackid)) == NULL) return -1; if (_af_set_sample_format(&track->v, sampleFormat, sampleWidth) == AF_FAIL) return -1; track->ms.modulesdirty = AF_TRUE; return 0; } /* XXXmpruett fix the version */ int afGetFileFormat (AFfilehandle file, int *version) { if (!_af_filehandle_ok(file)) return -1; if (version != NULL) { if (_af_units[file->fileFormat].getversion) *version = _af_units[file->fileFormat].getversion(file); else *version = 0; } return file->fileFormat; } int afSetVirtualChannels (AFfilehandle file, int trackid, int channelCount) { _Track *track; if (!_af_filehandle_ok(file)) return -1; if ((track = _af_filehandle_get_track(file, trackid)) == NULL) return -1; track->v.channelCount = channelCount; track->ms.modulesdirty = AF_TRUE; if (track->channelMatrix) free(track->channelMatrix); track->channelMatrix = NULL; return 0; } double afGetVirtualRate (AFfilehandle file, int trackid) { _Track *track; if ((track = _af_filehandle_get_track(file, trackid)) == NULL) return -1; return track->v.sampleRate; } int afSetVirtualRate (AFfilehandle file, int trackid, double rate) { _Track *track; if (!_af_filehandle_ok(file)) return -1; if ((track = _af_filehandle_get_track(file, trackid)) == NULL) return -1; if (rate < 0) { _af_error(AF_BAD_RATE, "invalid sampling rate %.30g", rate); return -1; } track->v.sampleRate = rate; track->ms.modulesdirty = AF_TRUE; return 0; } void afSetChannelMatrix (AFfilehandle file, int trackid, double* matrix) { _Track *track; if (!_af_filehandle_ok(file)) return; if ((track = _af_filehandle_get_track(file, trackid)) == NULL) return; if (track->channelMatrix != NULL) free(track->channelMatrix); track->channelMatrix = NULL; if (matrix != NULL) { int i, size; size = track->v.channelCount * track->f.channelCount; track->channelMatrix = (double *) malloc(size * sizeof (double)); for (i = 0; i < size; i++) track->channelMatrix[i] = matrix[i]; } } int afGetVirtualChannels (AFfilehandle file, int trackid) { _Track *track; if ((track = _af_filehandle_get_track(file, trackid)) == NULL) return -1; return track->v.channelCount; }