DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

WaveFile.h (8182B)


      1 /*
      2 ===========================================================================
      3 
      4 Doom 3 BFG Edition GPL Source Code
      5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 
      6 
      7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").  
      8 
      9 Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
     10 it under the terms of the GNU General Public License as published by
     11 the Free Software Foundation, either version 3 of the License, or
     12 (at your option) any later version.
     13 
     14 Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
     15 but WITHOUT ANY WARRANTY; without even the implied warranty of
     16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17 GNU General Public License for more details.
     18 
     19 You should have received a copy of the GNU General Public License
     20 along with Doom 3 BFG Edition Source Code.  If not, see <http://www.gnu.org/licenses/>.
     21 
     22 In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code.  If not, please request a copy in writing from id Software at the address below.
     23 
     24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
     25 
     26 ===========================================================================
     27 */
     28 #ifndef __WAVEFILE_H
     29 #define __WAVEFILE_H
     30 
     31 /*
     32 ================================================================================================
     33 Contains the WaveFile declaration.
     34 ================================================================================================
     35 */
     36 
     37 /*
     38 ================================================
     39 idWaveFile is used for reading generic RIFF WAVE files.
     40 ================================================
     41 */
     42 class idWaveFile {
     43 public:
     44 	ID_INLINE 	idWaveFile();
     45 	ID_INLINE 	~idWaveFile();
     46 
     47 	bool		Open( const char * filename );
     48 	void		Close();
     49 	uint32		SeekToChunk( uint32 id );
     50 	size_t		Read( void * buffer, size_t len ) { return file->Read( buffer, len ); }
     51 	uint32		GetChunkOffset( uint32 id );
     52 
     53 	ID_TIME_T	Timestamp() { return file->Timestamp(); }
     54 	const char * Name() { return ( file == NULL ? "" : file->GetName() ); }
     55 
     56 	// This maps to the channel mask in waveFmtExtensible_t
     57 	enum {
     58 		CHANNEL_INDEX_FRONT_LEFT,
     59 		CHANNEL_INDEX_FRONT_RIGHT,
     60 		CHANNEL_INDEX_FRONT_CENTER,
     61 		CHANNEL_INDEX_LOW_FREQUENCY,
     62 		CHANNEL_INDEX_BACK_LEFT,
     63 		CHANNEL_INDEX_BACK_RIGHT,
     64 		CHANNEL_INDEX_FRONT_LEFT_CENTER,
     65 		CHANNEL_INDEX_FRONT_RIGHT_CENTER,
     66 		CHANNEL_INDEX_BACK_CENTER,
     67 		CHANNEL_INDEX_SIDE_LEFT,
     68 		CHANNEL_INDEX_SIDE_RIGHT,
     69 		CHANNEL_INDEX_MAX
     70 	};
     71 	enum {
     72 		CHANNEL_MASK_FRONT_LEFT			= BIT( CHANNEL_INDEX_FRONT_LEFT ),
     73 		CHANNEL_MASK_FRONT_RIGHT		= BIT( CHANNEL_INDEX_FRONT_RIGHT ),
     74 		CHANNEL_MASK_FRONT_CENTER		= BIT( CHANNEL_INDEX_FRONT_CENTER ),
     75 		CHANNEL_MASK_LOW_FREQUENCY		= BIT( CHANNEL_INDEX_LOW_FREQUENCY ),
     76 		CHANNEL_MASK_BACK_LEFT			= BIT( CHANNEL_INDEX_BACK_LEFT ),
     77 		CHANNEL_MASK_BACK_RIGHT			= BIT( CHANNEL_INDEX_BACK_RIGHT ),
     78 		CHANNEL_MASK_FRONT_LEFT_CENTER	= BIT( CHANNEL_INDEX_FRONT_LEFT_CENTER ),
     79 		CHANNEL_MASK_FRONT_RIGHT_CENTER	= BIT( CHANNEL_INDEX_FRONT_RIGHT_CENTER ),
     80 		CHANNEL_MASK_BACK_CENTER		= BIT( CHANNEL_INDEX_BACK_CENTER ),
     81 		CHANNEL_MASK_SIDE_LEFT			= BIT( CHANNEL_INDEX_SIDE_LEFT ),
     82 		CHANNEL_MASK_SIDE_RIGHT			= BIT( CHANNEL_INDEX_SIDE_RIGHT ),
     83 		CHANNEL_MASK_ALL				= BIT( CHANNEL_INDEX_MAX ) - 1,
     84 	};
     85 
     86 	// This matches waveFmt_t::formatTag
     87 	// These are the only wave formats that we understand
     88 	enum {
     89 		FORMAT_UNKNOWN		= 0x0000,
     90 		FORMAT_PCM			= 0x0001,
     91 		FORMAT_ADPCM		= 0x0002,
     92 		FORMAT_XMA2			= 0x0166,
     93 		FORMAT_EXTENSIBLE	= 0xFFFF,
     94 	};
     95 
     96 #pragma pack( push, 1 )
     97 	struct waveFmt_t {
     98 		static const uint32 id = 'fmt ';
     99 		// This is the basic data we'd expect to see in any valid wave file
    100 		struct basic_t {
    101 			uint16 formatTag;
    102 			uint16 numChannels;
    103 			uint32 samplesPerSec;
    104 			uint32 avgBytesPerSec;
    105 			uint16 blockSize;
    106 			uint16 bitsPerSample;
    107 		} basic;
    108 		// Some wav file formats have extra data after the basic header
    109 		uint16 extraSize;
    110 		// We have a few known formats that we handle:
    111 		union extra_t {
    112 			// Valid if basic.formatTag == FORMAT_EXTENSIBLE
    113 			struct extensible_t {
    114 				uint16 validBitsPerSample;	// Valid bits in each sample container
    115 				uint32 channelMask;			// Positions of the audio channels
    116 				struct guid_t {
    117 					uint32 data1;
    118 					uint16 data2;
    119 					uint16 data3;
    120 					uint16 data4;
    121 					byte data5[ 6 ];
    122 				} subFormat;				// Format identifier GUID
    123 			} extensible;
    124 			// Valid if basic.formatTag == FORMAT_ADPCM
    125 			// The microsoft ADPCM struct has a zero-sized array at the end
    126 			// but the array is always 7 entries, so we set it to that size
    127 			// so we can embed it in our format union.  Otherwise, the struct
    128 			// is exactly the same as the one in audiodefs.h
    129 			struct adpcm_t {
    130 				uint16 samplesPerBlock;
    131 				uint16 numCoef;
    132 				struct adpcmcoef_t {
    133 					short coef1;
    134 					short coef2;
    135 				} aCoef[7];  // Always 7 coefficient pairs for MS ADPCM
    136 			} adpcm;
    137 			// Valid if basic.formatTag == FORMAT_XMA2
    138 			struct xma2_t {
    139 				uint16 numStreams;		// Number of audio streams (1 or 2 channels each)
    140 				uint32 channelMask;		// matches the CHANNEL_MASK enum above
    141 				uint32 samplesEncoded;	// Total number of PCM samples the file decodes to
    142 				uint32 bytesPerBlock;	// XMA block size (but the last one may be shorter)
    143 				uint32 playBegin;		// First valid sample in the decoded audio
    144 				uint32 playLength;		// Length of the valid part of the decoded audio
    145 				uint32 loopBegin;		// Beginning of the loop region in decoded sample terms
    146 				uint32 loopLength;		// Length of the loop region in decoded sample terms
    147 				byte   loopCount;		// Number of loop repetitions; 255 = infinite
    148 				byte   encoderVersion;	// Version of XMA encoder that generated the file
    149 				uint16 blockCount;		// XMA blocks in file (and entries in its seek table)
    150 			} xma2;
    151 		} extra;
    152 	};
    153 
    154 #pragma pack( pop )
    155 
    156 	struct dataChunk_t {
    157 		static const uint32 id = 'data';
    158 		uint32 size;
    159 		void * data;
    160 	};
    161 
    162 	struct formatChunk_t {
    163 		static const uint32 id = 'fmt ';
    164 		uint32 size;
    165 		uint16 compressionCode;
    166 		uint16 numChannels;
    167 		uint32 sampleRate;
    168 		uint32 averageBytesPerSecond;
    169 		uint16 blockAlign;
    170 		uint16 bitsPerSample;
    171 		uint16 numExtraFormatByte;
    172 	};
    173 
    174 	struct samplerChunk_t {
    175 		static const uint32 id = 'smpl';
    176 		uint32 manufacturer;		// ignored
    177 		uint32 product;				// ignored
    178 		uint32 samplePeriod;		// ignored (normally 1000000000/samplesPerSec)
    179 		uint32 MIDIUnityNote;		// ignored
    180 		uint32 MIDIPitchFraction;	// ignored
    181 		uint32 SMPTEFormat;			// ignored
    182 		uint32 SMPTEOffset;			// ignored
    183 		uint32 numSampleLoops;		// number of samples in wave file
    184 		uint32 extraSamplerData;	// ignored, should always be 0
    185 	};
    186 
    187 	struct sampleData_t {
    188 		uint32 identifier;		// ignored
    189 		uint32 type;			// 0 for loop 33 multi-sample sample type
    190 		uint32 start;			// start of the loop point
    191 		uint32 end;				// end of the loop point
    192 		uint32 fraction;		// ignored
    193 		uint32 playCount;		// ignored	
    194 	};
    195 
    196 	const char * ReadWaveFormat( waveFmt_t & waveFmt );
    197 	static bool  ReadWaveFormatDirect( waveFmt_t & format, idFile *file );
    198 	static bool  WriteWaveFormatDirect( waveFmt_t & format, idFile *file );
    199 	static bool  WriteSampleDataDirect( idList< sampleData_t > & sampleData, idFile *file );
    200 	static bool  WriteDataDirect( char * _data, uint32 size, idFile * file );
    201 	static bool  WriteHeaderDirect( uint32 fileSize, idFile * file );
    202 
    203 	bool		 ReadLoopData( int & start, int & end );
    204 	
    205 private:
    206 	idFile *					file;
    207 
    208 	struct chunk_t {
    209 		uint32 id;
    210 		uint32 size;
    211 		uint32 offset;
    212 	};
    213 
    214 	idStaticList< chunk_t, 32 >	chunks;
    215 
    216 
    217 };
    218 
    219 /*
    220 ========================
    221 idWaveFile::idWaveFile
    222 ========================
    223 */
    224 ID_INLINE idWaveFile::idWaveFile() : file( NULL ) {
    225 }
    226 
    227 /*
    228 ========================
    229 idWaveFile::~idWaveFile
    230 ========================
    231 */
    232 ID_INLINE idWaveFile::~idWaveFile() {
    233 	Close();
    234 }
    235 
    236 #endif // !__WAVEFILE_H__