sm64pc/tools/audiofile-0.3.6/libaudiofile/Setup.cpp

561 lines
12 KiB
C++

/*
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 <stdlib.h>
#include <string.h>
#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; i<trackCount; i++)
{
tracks[i] = _af_default_tracksetup;
tracks[i].id = AF_DEFAULT_TRACK + i;
/* XXXmpruett deal with compression */
_af_set_sample_format(&tracks[i].f, tracks[i].f.sampleFormat,
tracks[i].f.sampleWidth);
if (tracks[i].markerCount == 0)
tracks[i].markers = NULL;
else
{
tracks[i].markers = (MarkerSetup *) _af_calloc(tracks[i].markerCount,
sizeof (MarkerSetup));
if (tracks[i].markers == NULL)
return NULL;
for (int j=0; j<tracks[i].markerCount; j++)
{
tracks[i].markers[j].id = j+1;
tracks[i].markers[j].name = _af_strdup("");
if (tracks[i].markers[j].name == NULL)
return NULL;
tracks[i].markers[j].comment = _af_strdup("");
if (tracks[i].markers[j].comment == NULL)
return NULL;
}
}
}
return tracks;
}
InstrumentSetup *_af_instsetup_new (int instrumentCount)
{
InstrumentSetup *instruments;
if (instrumentCount == 0)
return NULL;
instruments = (InstrumentSetup *) _af_calloc(instrumentCount, sizeof (InstrumentSetup));
if (instruments == NULL)
return NULL;
for (int i=0; i<instrumentCount; i++)
{
instruments[i] = _af_default_instrumentsetup;
instruments[i].id = AF_DEFAULT_INST + i;
if (instruments[i].loopCount == 0)
instruments[i].loops = NULL;
else
{
instruments[i].loops = (LoopSetup *) _af_calloc(instruments[i].loopCount, sizeof (LoopSetup));
if (instruments[i].loops == NULL)
return NULL;
for (int j=0; j<instruments[i].loopCount; j++)
instruments[i].loops[j].id = j+1;
}
}
return instruments;
}
AFfilesetup afNewFileSetup (void)
{
AFfilesetup setup;
setup = (_AFfilesetup *) _af_malloc(sizeof (_AFfilesetup));
if (setup == NULL) return AF_NULL_FILESETUP;
*setup = _af_default_file_setup;
setup->tracks = _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; i<setup->miscellaneousCount; 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; i<setup->tracks[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; i<setup->trackCount; 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<intmax_t>(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<intmax_t>(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; i<setup->trackCount; 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; j<setup->tracks[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; i<newsetup->instrumentCount; 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<trackCount; i++)
{
if (tracks[i].id == trackID)
return &tracks[i];
}
_af_error(AF_BAD_TRACKID, "bad track id %d", trackID);
return NULL;
}
InstrumentSetup *_AFfilesetup::getInstrument(int instrumentID)
{
for (int i=0; i < instrumentCount; i++)
if (instruments[i].id == instrumentID)
return &instruments[i];
_af_error(AF_BAD_INSTID, "invalid instrument id %d", instrumentID);
return NULL;
}
MiscellaneousSetup *_AFfilesetup::getMiscellaneous(int miscellaneousID)
{
for (int i=0; i<miscellaneousCount; i++)
{
if (miscellaneous[i].id == miscellaneousID)
return &miscellaneous[i];
}
_af_error(AF_BAD_MISCID, "bad miscellaneous id %d", miscellaneousID);
return NULL;
}