diff options
Diffstat (limited to 'src/loris/AiffData.h')
-rw-r--r-- | src/loris/AiffData.h | 361 |
1 files changed, 361 insertions, 0 deletions
diff --git a/src/loris/AiffData.h b/src/loris/AiffData.h new file mode 100644 index 0000000..fb07ed2 --- /dev/null +++ b/src/loris/AiffData.h @@ -0,0 +1,361 @@ +/* + * This is the Loris C++ Class Library, implementing analysis, + * manipulation, and synthesis of digitized sounds using the Reassigned + * Bandwidth-Enhanced Additive Sound Model. + * + * Loris is Copyright (c) 1999-2010 by Kelly Fitz and Lippold Haken + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * + * AiffData.h + * + * Declarations of import and export functions. + * + * Kelly Fitz, 17 Sept 2003 + * loris@cerlsoundgroup.org + * + * http://www.cerlsoundgroup.org/Loris/ + * + */ + +#include "Marker.h" + +#include <string> +#include <vector> + +// in case configure wasn't run (no config.h), +// pick some (hopefully-) reasonable values for +// these things and hope for the best... +#if ! defined( SIZEOF_SHORT ) +#define SIZEOF_SHORT 2 +#endif + +#if ! defined( SIZEOF_INT ) +#define SIZEOF_INT 4 +#endif + +#if ! defined( SIZEOF_LONG ) +#define SIZEOF_LONG 4 // not for DEC Alpha! +#endif + + +#if SIZEOF_SHORT == 2 +typedef short Int_16; +typedef unsigned short Uint_16; +#elif SIZEOF_INT == 2 +typedef int Int_16; +typedef unsigned int Uint_16; +#else +#error "cannot find an appropriate type for 16-bit integers" +#endif + +#if SIZEOF_INT == 4 +typedef int Int_32; +typedef unsigned int Uint_32; +#elif SIZEOF_LONG == 4 +typedef long Int_32; +typedef unsigned long Uint_32; +#else +#error "cannot find an appropriate type for 32-bit integers" +#endif + + +// begin namespace +namespace Loris { + +// -- chunk types -- +enum +{ + ContainerId = 0x464f524d, // 'FORM' + AiffType = 0x41494646, // 'AIFF' + CommonId = 0x434f4d4d, // 'COMM' + ApplicationSpecificId = 0x4150504c, // 'APPL' + SosEnvelopesId = 0x534f5365, // 'SOSe' + SoundDataId = 0x53534e44, // 'SSND' + InstrumentId = 0x494e5354, // 'INST' + MarkerId = 0x4d41524b // 'MARK' +}; + +typedef Uint_32 ID; +typedef char Byte; + +struct CkHeader +{ + ID id; + Uint_32 size; + + // providing this default constructor + // gives clients a way to determine whether + // a chunk has been read and assigned: + CkHeader( void ) : id(0), size(0) {} +}; + +struct ContainerCk +{ + CkHeader header; + ID formType; +}; + +struct CommonCk +{ + CkHeader header; + Int_16 channels; // number of channels + Int_32 sampleFrames; // channel independent sample frames + Int_16 bitsPerSample; // number of bits per sample + double srate; // sampling rate (stored in IEEE 10 byte format) +}; + +struct SoundDataCk +{ + CkHeader header; + Uint_32 offset; + Uint_32 blockSize; + + // sample frames follow + std::vector< Byte > sampleBytes; +}; + +struct MarkerCk +{ + CkHeader header; + Uint_16 numMarkers; + + struct Marker + { + Uint_16 markerID; + Uint_32 position; // position in uncompressed samples + std::string markerName; + }; + + std::vector< MarkerCk::Marker > markers; +}; + +struct InstrumentCk +{ + CkHeader header; + Byte baseNote; /* all notes are MIDI note numbers */ + Byte detune; /* cents off, only -50 to +50 are significant */ + Byte lowNote; + Byte highNote; + Byte lowVelocity; /* 1 to 127 */ + Byte highVelocity; /* 1 to 127 */ + Int_16 gain; /* in dB, 0 is normal */ + + struct Loop + { + Int_16 playMode; /* 0 - no loop, 1 - forward looping, 2 - backward looping */ + Uint_16 beginLoop; /* this is a reference to a markerID, so you always + تتتتتتتتتتتتتتتتتتتتتتتتتتتتتتتت have to work with MARK and INST together!! */ + Uint_16 endLoop; + }; + + Loop sustainLoop; + Loop releaseLoop; +}; + + +struct SosEnvelopesCk +{ + CkHeader header; + Int_32 signature; // For SOS, should be 'SOSe' + Int_32 enhanced; // 0 for sine-only, 1 for bandwidth-enhanced + Int_32 validPartials; // Number of partials with data in them; the file must + // be padded out to the next higher 2**n partials; + // this number is doubled for enhanced files + + // skip validPartials * sizeof(Int_32) bytes of junk here + Int_32 resolution; // frame duration in microseconds + Int_32 quasiHarmonic; // how many of the partials are quasiharmonic + // skip + // (4*LargestLabel + 8 - validPartials - 2) * sizeof(Int_32) + // bytes of junk here + +/* + // this stuff is unbelievably nasty! + +#define initPhaseLth ( 4*LargestLabel + 8 ) + Int_32 initPhase[initPhaseLth]; // obsolete initial phase array; is VARIABLE LENGTH array + // this is big enough for a max of 512 enhanced partials plus values below +// Int_32 resolution; // frame duration in microseconds + #define SOSresolution( es ) initPhase[ spcEI.enhanced \ + ? 2 * spcEI.numPartials : spcEI.numPartials] + // follows the initPhase[] array + + +// Int_32 quasiHarmonic; // how many of the partials are quasiharmonic + #define SOSquasiHarmonic( es ) initPhase[ spcEI.enhanced \ + ? 2 * spcEI.numPartials + 1 : spcEI.numPartials + 1] + // follows the initPhase[] array +*/ +}; + +// --------------------------------------------------------------------------- +// readChunkHeader +// --------------------------------------------------------------------------- +// Read the id and chunk size from the current file position. +// Let exceptions propogate. +// +std::istream & +readChunkHeader( std::istream & s, CkHeader & h ); + + +// --------------------------------------------------------------------------- +// readApplicationSpecifcData +// --------------------------------------------------------------------------- +// Read the data in the ApplicationSpecific chunk, assume the stream is +// correctly positioned, and that the chunk header has already been read. +// +// Look for data specific to SPC files. Any other kind of Application +// Specific data is ignored. +// +std::istream & +readApplicationSpecifcData( std::istream & s, SosEnvelopesCk & ck, unsigned long chunkSize ); + + +// --------------------------------------------------------------------------- +// readCommonData +// --------------------------------------------------------------------------- +// Read the data in the Common chunk, assume the stream is correctly +// positioned, and that the chunk header has already been read. +// +std::istream & +readCommonData( std::istream & s, CommonCk & ck, unsigned long chunkSize ); + +// --------------------------------------------------------------------------- +// readContainer +// --------------------------------------------------------------------------- +// +std::istream & +readContainer( std::istream & s, ContainerCk & ck, unsigned long chunkSize ); + +// --------------------------------------------------------------------------- +// readInstrumentData +// --------------------------------------------------------------------------- +// +std::istream & +readInstrumentData( std::istream & s, InstrumentCk & ck, unsigned long chunkSize ); + +// --------------------------------------------------------------------------- +// readMarkerData +// --------------------------------------------------------------------------- +// +std::istream & +readMarkerData( std::istream & s, MarkerCk & ck, unsigned long chunkSize ); + +// --------------------------------------------------------------------------- +// readSampleData +// --------------------------------------------------------------------------- +// Read the data in the Sound Data chunk, assume the stream is correctly +// positioned, and that the chunk header has already been read. +// +std::istream & +readSampleData( std::istream & s, SoundDataCk & ck, unsigned long chunkSize ); + +// --------------------------------------------------------------------------- +// configureCommonCk +// --------------------------------------------------------------------------- +void +configureCommonCk( CommonCk & ck, unsigned long nFrames, unsigned int nChans, + unsigned int bps, double srate ); + +// --------------------------------------------------------------------------- +// configureContainer +// --------------------------------------------------------------------------- +// dataSize is the combined size of all other chunks in file. Configure +// them first, then add their sizes (with headers!). +// +void +configureContainer( ContainerCk & ck, unsigned long dataSize ); + +// --------------------------------------------------------------------------- +// configureInstrumentCk +// --------------------------------------------------------------------------- +void +configureInstrumentCk( InstrumentCk & ck, double midiNoteNum ); + +// --------------------------------------------------------------------------- +// configureMarkerCk +// --------------------------------------------------------------------------- +void +configureMarkerCk( MarkerCk & ck, const std::vector< Marker > & markers, + double srate ); + +// --------------------------------------------------------------------------- +// configureSoundDataCk +// --------------------------------------------------------------------------- +// +void +configureSoundDataCk( SoundDataCk & ck, const std::vector< double > & samples, + unsigned int bps ); + +// --------------------------------------------------------------------------- +// writeCommon +// --------------------------------------------------------------------------- +// +std::ostream & +writeCommonData( std::ostream & s, const CommonCk & ck ); + +// --------------------------------------------------------------------------- +// writeContainer +// --------------------------------------------------------------------------- +// +std::ostream & +writeContainer( std::ostream & s, const ContainerCk & ck ); + +// --------------------------------------------------------------------------- +// writeInstrumentData +// --------------------------------------------------------------------------- +std::ostream & +writeInstrumentData( std::ostream & s, const InstrumentCk & ck ); + +// --------------------------------------------------------------------------- +// writeMarkerData +// --------------------------------------------------------------------------- +std::ostream & +writeMarkerData( std::ostream & s, const MarkerCk & ck ); + +// --------------------------------------------------------------------------- +// writeSampleData +// --------------------------------------------------------------------------- +// +std::ostream & +writeSampleData( std::ostream & s, const SoundDataCk & ck ); + +// --------------------------------------------------------------------------- +// convertBytesToSamples +// --------------------------------------------------------------------------- +// Convert sample bytes to double precision floating point samples +// (-1.0, 1.0). The samples vector is resized to fit exactly as many +// samples as are represented in the bytes vector, and any prior +// contents are overwritten. +// +void +convertBytesToSamples( const std::vector< Byte > & bytes, + std::vector< double > & samples, unsigned int bps ); + +// --------------------------------------------------------------------------- +// convertSamplesToBytes +// --------------------------------------------------------------------------- +// Convert floating point samples (-1.0, 1.0) to bytes. +// The bytes vector is resized to fit exactly as many +// samples as are stored in the samples vector, and any prior +// contents are overwritten. +// +void +convertSamplesToBytes( const std::vector< double > & samples, + std::vector< Byte > & bytes, unsigned int bps ); + +} // end of namespace |