/* Audio File Library 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 Lesser General Public License as published by the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /* Setup.cpp */ #include "config.h" #include "Setup.h" #include #include #include "FileHandle.h" #include "Instrument.h" #include "Marker.h" #include "Track.h" #include "afinternal.h" #include "byteorder.h" #include "audiofile.h" #include "pcm.h" #include "units.h" #include "util.h" static const _AFfilesetup _af_default_file_setup = { _AF_VALID_FILESETUP, /* valid */ #if WORDS_BIGENDIAN AF_FILE_AIFFC, /* file format */ #else AF_FILE_WAVE, /* file format */ #endif false, /* trackSet */ false, /* instrumentSet */ false, /* miscellaneousSet */ 1, /* trackCount */ NULL, /* tracks */ 1, /* instrumentCount */ NULL, /* instruments */ 0, /* miscellaneousCount */ NULL /* miscellaneous */ }; static const InstrumentSetup _af_default_instrumentsetup = { 0, /* id */ 2, /* loopCount */ NULL, /* loops */ false /* loopSet */ }; static const TrackSetup _af_default_tracksetup = { 0, { 44100.0, AF_SAMPFMT_TWOSCOMP, 16, _AF_BYTEORDER_NATIVE, { SLOPE_INT16, 0, MIN_INT16, MAX_INT16 }, 2, AF_COMPRESSION_NONE, NULL }, false, /* rateSet */ false, /* sampleFormatSet */ false, /* sampleWidthSet */ false, /* byteOrderSet */ false, /* channelCountSet */ false, /* compressionSet */ false, /* aesDataSet */ false, /* markersSet */ false, /* dataOffsetSet */ false, /* frameCountSet */ 4, /* markerCount */ NULL, /* markers */ 0, /* dataOffset */ 0 /* frameCount */ }; TrackSetup *_af_tracksetup_new (int trackCount) { TrackSetup *tracks; if (trackCount == 0) return NULL; tracks = (TrackSetup *) _af_calloc(trackCount, sizeof (TrackSetup)); if (tracks == NULL) return NULL; for (int i=0; itracks = _af_tracksetup_new(setup->trackCount); setup->instruments = _af_instsetup_new(setup->instrumentCount); if (setup->miscellaneousCount == 0) setup->miscellaneous = NULL; else { setup->miscellaneous = (MiscellaneousSetup *) _af_calloc(setup->miscellaneousCount, sizeof (MiscellaneousSetup)); for (int i=0; imiscellaneousCount; i++) { setup->miscellaneous[i].id = i+1; setup->miscellaneous[i].type = 0; setup->miscellaneous[i].size = 0; } } return setup; } /* Free the specified track's markers and their subfields. */ void _af_setup_free_markers (AFfilesetup setup, int trackno) { if (setup->tracks[trackno].markerCount != 0) { for (int i=0; itracks[trackno].markerCount; i++) { free(setup->tracks[trackno].markers[i].name); free(setup->tracks[trackno].markers[i].comment); } free(setup->tracks[trackno].markers); } setup->tracks[trackno].markers = NULL; setup->tracks[trackno].markerCount = 0; } /* Free the specified setup's tracks and their subfields. */ void _af_setup_free_tracks (AFfilesetup setup) { if (setup->tracks) { for (int i=0; itrackCount; i++) { _af_setup_free_markers(setup, i); } free(setup->tracks); } setup->tracks = NULL; setup->trackCount = 0; } /* Free the specified setup's instruments and their subfields. */ void _af_setup_free_instruments (AFfilesetup setup) { if (setup->instruments) { for (int i=0; i < setup->instrumentCount; i++) setup->instruments[i].freeLoops(); free(setup->instruments); } setup->instruments = NULL; setup->instrumentCount = 0; } void afFreeFileSetup (AFfilesetup setup) { if (!_af_filesetup_ok(setup)) return; _af_setup_free_tracks(setup); _af_setup_free_instruments(setup); if (setup->miscellaneousCount) { free(setup->miscellaneous); setup->miscellaneous = NULL; setup->miscellaneousCount = 0; } memset(setup, 0, sizeof (_AFfilesetup)); free(setup); } void afInitFileFormat (AFfilesetup setup, int filefmt) { if (!_af_filesetup_ok(setup)) return; if (filefmt < 0 || filefmt >= _AF_NUM_UNITS) { _af_error(AF_BAD_FILEFMT, "unrecognized file format %d", filefmt); return; } if (!_af_units[filefmt].implemented) { _af_error(AF_BAD_NOT_IMPLEMENTED, "%s format not currently supported", _af_units[filefmt].name); return; } setup->fileFormat = filefmt; } void afInitChannels (AFfilesetup setup, int trackid, int channels) { if (!_af_filesetup_ok(setup)) return; TrackSetup *track = setup->getTrack(trackid); if (!track) return; if (channels < 1) { _af_error(AF_BAD_CHANNELS, "invalid number of channels %d", channels); return; } track->f.channelCount = channels; track->channelCountSet = true; } void afInitSampleFormat (AFfilesetup setup, int trackid, int sampfmt, int sampwidth) { if (!_af_filesetup_ok(setup)) return; TrackSetup *track = setup->getTrack(trackid); if (!track) return; _af_set_sample_format(&track->f, sampfmt, sampwidth); track->sampleFormatSet = true; track->sampleWidthSet = true; } void afInitByteOrder (AFfilesetup setup, int trackid, int byteorder) { if (!_af_filesetup_ok(setup)) return; TrackSetup *track = setup->getTrack(trackid); if (!track) return; if (byteorder != AF_BYTEORDER_BIGENDIAN && byteorder != AF_BYTEORDER_LITTLEENDIAN) { _af_error(AF_BAD_BYTEORDER, "invalid byte order %d", byteorder); return; } track->f.byteOrder = byteorder; track->byteOrderSet = true; } void afInitRate (AFfilesetup setup, int trackid, double rate) { if (!_af_filesetup_ok(setup)) return; TrackSetup *track = setup->getTrack(trackid); if (!track) return; if (rate <= 0.0) { _af_error(AF_BAD_RATE, "invalid sample rate %.30g", rate); return; } track->f.sampleRate = rate; track->rateSet = true; } /* track data: data offset within the file (initialized for raw reading only) */ void afInitDataOffset (AFfilesetup setup, int trackid, AFfileoffset offset) { if (!_af_filesetup_ok(setup)) return; TrackSetup *track = setup->getTrack(trackid); if (!track) return; if (offset < 0) { _af_error(AF_BAD_DATAOFFSET, "invalid data offset %jd", static_cast(offset)); return; } track->dataOffset = offset; track->dataOffsetSet = true; } /* track data: data offset within the file (initialized for raw reading only) */ void afInitFrameCount (AFfilesetup setup, int trackid, AFfileoffset count) { if (!_af_filesetup_ok(setup)) return; TrackSetup *track = setup->getTrack(trackid); if (!track) return; if (count < 0) { _af_error(AF_BAD_FRAMECNT, "invalid frame count %jd", static_cast(count)); return; } track->frameCount = count; track->frameCountSet = true; } #define alloccopy(type, n, var, copyfrom) \ { \ if (n == 0) \ var = NULL; \ else \ { \ if ((var = (type *) _af_calloc(n, sizeof (type))) == NULL) \ goto fail; \ memcpy((var), (copyfrom), (n) * sizeof (type)); \ } \ } AFfilesetup _af_filesetup_copy (const _AFfilesetup *setup, const _AFfilesetup *defaultSetup, bool copyMarks) { AFfilesetup newsetup; int instrumentCount, miscellaneousCount, trackCount; newsetup = (_AFfilesetup *) _af_malloc(sizeof (_AFfilesetup)); if (newsetup == AF_NULL_FILESETUP) return AF_NULL_FILESETUP; *newsetup = *defaultSetup; newsetup->tracks = NULL; newsetup->instruments = NULL; newsetup->miscellaneous = NULL; /* Copy tracks. */ trackCount = setup->trackSet ? setup->trackCount : newsetup->trackSet ? newsetup->trackCount : 0; alloccopy(TrackSetup, trackCount, newsetup->tracks, setup->tracks); newsetup->trackCount = trackCount; /* Copy instruments. */ instrumentCount = setup->instrumentSet ? setup->instrumentCount : newsetup->instrumentSet ? newsetup->instrumentCount : 0; alloccopy(InstrumentSetup, instrumentCount, newsetup->instruments, setup->instruments); newsetup->instrumentCount = instrumentCount; /* Copy miscellaneous information. */ miscellaneousCount = setup->miscellaneousSet ? setup->miscellaneousCount : newsetup->miscellaneousSet ? newsetup->miscellaneousCount : 0; alloccopy(MiscellaneousSetup, miscellaneousCount, newsetup->miscellaneous, setup->miscellaneous); newsetup->miscellaneousCount = miscellaneousCount; for (int i=0; itrackCount; i++) { TrackSetup *track = &newsetup->tracks[i]; /* XXXmpruett set compression information */ if (!setup->tracks[i].markersSet && !copyMarks) { track->markers = NULL; track->markerCount = 0; continue; } alloccopy(MarkerSetup, setup->tracks[i].markerCount, track->markers, setup->tracks[i].markers); track->markerCount = setup->tracks[i].markerCount; for (int j=0; jtracks[i].markerCount; j++) { track->markers[j].name = _af_strdup(setup->tracks[i].markers[j].name); if (track->markers[j].name == NULL) goto fail; track->markers[j].comment = _af_strdup(setup->tracks[i].markers[j].comment); if (track->markers[j].comment == NULL) goto fail; } } for (int i=0; iinstrumentCount; i++) { InstrumentSetup *instrument = &newsetup->instruments[i]; alloccopy(LoopSetup, setup->instruments[i].loopCount, instrument->loops, setup->instruments[i].loops); } return newsetup; fail: if (newsetup->miscellaneous) free(newsetup->miscellaneous); if (newsetup->instruments) free(newsetup->instruments); if (newsetup->tracks) free(newsetup->tracks); if (newsetup) free(newsetup); return AF_NULL_FILESETUP; } TrackSetup *_AFfilesetup::getTrack(int trackID) { for (int i=0; i