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__