libgig 3.3.0
|
00001 /*************************************************************************** 00002 * * 00003 * libgig - C++ cross-platform Gigasampler format file access library * 00004 * * 00005 * Copyright (C) 2003-2009 by Christian Schoenebeck * 00006 * <cuse@users.sourceforge.net> * 00007 * * 00008 * This library is free software; you can redistribute it and/or modify * 00009 * it under the terms of the GNU General Public License as published by * 00010 * the Free Software Foundation; either version 2 of the License, or * 00011 * (at your option) any later version. * 00012 * * 00013 * This library is distributed in the hope that it will be useful, * 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 00016 * GNU General Public License for more details. * 00017 * * 00018 * You should have received a copy of the GNU General Public License * 00019 * along with this library; if not, write to the Free Software * 00020 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * 00021 * MA 02111-1307 USA * 00022 ***************************************************************************/ 00023 00024 #ifndef __RIFF_H__ 00025 #define __RIFF_H__ 00026 00027 #ifdef WIN32 00028 # define POSIX 0 00029 #endif 00030 00031 #ifndef POSIX 00032 # define POSIX 1 00033 #endif 00034 00035 #ifndef DEBUG 00036 # define DEBUG 0 00037 #endif 00038 00039 #include <string> 00040 #include <list> 00041 #include <map> 00042 #include <iostream> 00043 00044 #ifdef HAVE_CONFIG_H 00045 # include <config.h> 00046 #endif 00047 00048 #if POSIX 00049 # include <sys/types.h> 00050 # include <sys/stat.h> 00051 # include <fcntl.h> 00052 # include <unistd.h> 00053 #endif // POSIX 00054 00055 #ifdef _MSC_VER 00056 // Visual C++ 2008 doesn't have stdint.h 00057 typedef __int8 int8_t; 00058 typedef __int16 int16_t; 00059 typedef __int32 int32_t; 00060 typedef __int64 int64_t; 00061 typedef unsigned __int8 uint8_t; 00062 typedef unsigned __int16 uint16_t; 00063 typedef unsigned __int32 uint32_t; 00064 typedef unsigned __int64 uint64_t; 00065 #else 00066 #include <stdint.h> 00067 #endif 00068 00069 #ifdef WIN32 00070 # include <windows.h> 00071 typedef unsigned int uint; 00072 #endif // WIN32 00073 00074 #include <stdio.h> 00075 00076 #if WORDS_BIGENDIAN 00077 # define CHUNK_ID_RIFF 0x52494646 00078 # define CHUNK_ID_RIFX 0x52494658 00079 # define CHUNK_ID_LIST 0x4C495354 00080 #else // little endian 00081 # define CHUNK_ID_RIFF 0x46464952 00082 # define CHUNK_ID_RIFX 0x58464952 00083 # define CHUNK_ID_LIST 0x5453494C 00084 #endif // WORDS_BIGENDIAN 00085 00086 #define CHUNK_HEADER_SIZE 8 00087 #define LIST_HEADER_SIZE 12 00088 #define RIFF_HEADER_SIZE 12 00089 00090 00110 namespace RIFF { 00111 00112 /* just symbol prototyping */ 00113 class Chunk; 00114 class List; 00115 class File; 00116 00117 typedef std::string String; 00118 00120 typedef enum { 00121 stream_mode_read = 0, 00122 stream_mode_read_write = 1, 00123 stream_mode_closed = 2 00124 } stream_mode_t; 00125 00127 typedef enum { 00128 stream_ready = 0, 00129 stream_end_reached = 1, 00130 stream_closed = 2 00131 } stream_state_t; 00132 00134 typedef enum { 00135 stream_start = 0, 00136 stream_curpos = 1, 00137 stream_backward = 2, 00138 stream_end = 3 00139 } stream_whence_t; 00140 00142 typedef enum { 00143 endian_little = 0, 00144 endian_big = 1, 00145 endian_native = 2 00146 } endian_t; 00147 00153 class Chunk { 00154 public: 00155 Chunk(File* pFile, unsigned long StartPos, List* Parent); 00156 String GetChunkIDString(); 00157 uint32_t GetChunkID() { return ChunkID; } 00158 List* GetParent() { return pParent; } 00159 unsigned long GetSize() { return CurrentChunkSize; } 00160 unsigned long GetNewSize() { return NewChunkSize; } 00161 unsigned long GetPos() { return ulPos; } 00162 unsigned long GetFilePos() { return ulStartPos + ulPos; } 00163 unsigned long SetPos(unsigned long Where, stream_whence_t Whence = stream_start); 00164 unsigned long RemainingBytes(); 00165 stream_state_t GetState(); 00166 unsigned long Read(void* pData, unsigned long WordCount, unsigned long WordSize); 00167 unsigned long ReadInt8(int8_t* pData, unsigned long WordCount = 1); 00168 unsigned long ReadUint8(uint8_t* pData, unsigned long WordCount = 1); 00169 unsigned long ReadInt16(int16_t* pData, unsigned long WordCount = 1); 00170 unsigned long ReadUint16(uint16_t* pData, unsigned long WordCount = 1); 00171 unsigned long ReadInt32(int32_t* pData, unsigned long WordCount = 1); 00172 unsigned long ReadUint32(uint32_t* pData, unsigned long WordCount = 1); 00173 int8_t ReadInt8(); 00174 uint8_t ReadUint8(); 00175 int16_t ReadInt16(); 00176 uint16_t ReadUint16(); 00177 int32_t ReadInt32(); 00178 uint32_t ReadUint32(); 00179 unsigned long Write(void* pData, unsigned long WordCount, unsigned long WordSize); 00180 unsigned long WriteInt8(int8_t* pData, unsigned long WordCount = 1); 00181 unsigned long WriteUint8(uint8_t* pData, unsigned long WordCount = 1); 00182 unsigned long WriteInt16(int16_t* pData, unsigned long WordCount = 1); 00183 unsigned long WriteUint16(uint16_t* pData, unsigned long WordCount = 1); 00184 unsigned long WriteInt32(int32_t* pData, unsigned long WordCount = 1); 00185 unsigned long WriteUint32(uint32_t* pData, unsigned long WordCount = 1); 00186 void* LoadChunkData(); 00187 void ReleaseChunkData(); 00188 void Resize(int iNewSize); 00189 virtual ~Chunk(); 00190 protected: 00191 uint32_t ChunkID; 00192 uint32_t CurrentChunkSize; /* in bytes */ 00193 uint32_t NewChunkSize; /* in bytes (if chunk was scheduled to be resized) */ 00194 List* pParent; 00195 File* pFile; 00196 unsigned long ulStartPos; /* actual position in file where chunk (without header) starts */ 00197 unsigned long ulPos; /* # of bytes from ulStartPos */ 00198 uint8_t* pChunkData; 00199 unsigned long ulChunkDataSize; 00200 00201 Chunk(File* pFile); 00202 Chunk(File* pFile, List* pParent, uint32_t uiChunkID, uint uiBodySize); 00203 void ReadHeader(unsigned long fPos); 00204 void WriteHeader(unsigned long fPos); 00205 unsigned long ReadSceptical(void* pData, unsigned long WordCount, unsigned long WordSize); 00206 inline void swapBytes_16(void* Word) { 00207 uint8_t byteCache = *((uint8_t*) Word); 00208 *((uint8_t*) Word) = *((uint8_t*) Word + 1); 00209 *((uint8_t*) Word + 1) = byteCache; 00210 } 00211 inline void swapBytes_32(void* Word) { 00212 uint8_t byteCache = *((uint8_t*) Word); 00213 *((uint8_t*) Word) = *((uint8_t*) Word + 3); 00214 *((uint8_t*) Word + 3) = byteCache; 00215 byteCache = *((uint8_t*) Word + 1); 00216 *((uint8_t*) Word + 1) = *((uint8_t*) Word + 2); 00217 *((uint8_t*) Word + 2) = byteCache; 00218 } 00219 inline void swapBytes(void* Word, unsigned long WordSize) { 00220 uint8_t byteCache; 00221 unsigned long lo = 0, hi = WordSize - 1; 00222 for (; lo < hi; hi--, lo++) { 00223 byteCache = *((uint8_t*) Word + lo); 00224 *((uint8_t*) Word + lo) = *((uint8_t*) Word + hi); 00225 *((uint8_t*) Word + hi) = byteCache; 00226 } 00227 } 00228 inline String convertToString(uint32_t word) { 00229 String result; 00230 for (int i = 0; i < 4; i++) { 00231 uint8_t byte = *((uint8_t*)(&word) + i); 00232 char c = byte; 00233 result += c; 00234 } 00235 return result; 00236 } 00237 virtual unsigned long WriteChunk(unsigned long ulWritePos, unsigned long ulCurrentDataOffset); 00238 virtual void __resetPos(); 00239 00240 friend class List; 00241 }; 00242 00248 class List : public Chunk { 00249 public: 00250 List(File* pFile, unsigned long StartPos, List* Parent); 00251 String GetListTypeString(); 00252 uint32_t GetListType() { return ListType; } 00253 Chunk* GetSubChunk(uint32_t ChunkID); 00254 List* GetSubList(uint32_t ListType); 00255 Chunk* GetFirstSubChunk(); 00256 Chunk* GetNextSubChunk(); 00257 List* GetFirstSubList(); 00258 List* GetNextSubList(); 00259 unsigned int CountSubChunks(); 00260 unsigned int CountSubChunks(uint32_t ChunkID); 00261 unsigned int CountSubLists(); 00262 unsigned int CountSubLists(uint32_t ListType); 00263 Chunk* AddSubChunk(uint32_t uiChunkID, uint uiBodySize); 00264 List* AddSubList(uint32_t uiListType); 00265 void DeleteSubChunk(Chunk* pSubChunk); 00266 void MoveSubChunk(Chunk* pSrc, Chunk* pDst); 00267 virtual ~List(); 00268 protected: 00269 typedef std::map<uint32_t, RIFF::Chunk*> ChunkMap; 00270 typedef std::list<Chunk*> ChunkList; 00271 00272 uint32_t ListType; 00273 ChunkList* pSubChunks; 00274 ChunkMap* pSubChunksMap; 00275 ChunkList::iterator ChunksIterator; 00276 ChunkList::iterator ListIterator; 00277 00278 List(File* pFile); 00279 List(File* pFile, List* pParent, uint32_t uiListID); 00280 void ReadHeader(unsigned long fPos); 00281 void WriteHeader(unsigned long fPos); 00282 void LoadSubChunks(); 00283 void LoadSubChunksRecursively(); 00284 virtual unsigned long WriteChunk(unsigned long ulWritePos, unsigned long ulCurrentDataOffset); 00285 virtual void __resetPos(); 00286 void DeleteChunkList(); 00287 }; 00288 00295 class File : public List { 00296 public: 00297 File(uint32_t FileType); 00298 File(const String& path); 00299 stream_mode_t GetMode(); 00300 bool SetMode(stream_mode_t NewMode); 00301 void SetByteOrder(endian_t Endian); 00302 String GetFileName(); 00303 virtual void Save(); 00304 virtual void Save(const String& path); 00305 virtual ~File(); 00306 protected: 00307 #if POSIX 00308 int hFileRead; 00309 int hFileWrite; 00310 #elif defined(WIN32) 00311 HANDLE hFileRead; 00312 HANDLE hFileWrite; 00313 #else 00314 FILE* hFileRead; 00315 FILE* hFileWrite; 00316 #endif // POSIX 00317 String Filename; 00318 bool bEndianNative; 00319 00320 void LogAsResized(Chunk* pResizedChunk); 00321 void UnlogResized(Chunk* pResizedChunk); 00322 friend class Chunk; 00323 friend class List; 00324 private: 00325 stream_mode_t Mode; 00326 ChunkList ResizedChunks; 00327 00328 unsigned long GetFileSize(); 00329 void ResizeFile(unsigned long ulNewSize); 00330 #if POSIX 00331 unsigned long __GetFileSize(int hFile); 00332 #elif defined(WIN32) 00333 unsigned long __GetFileSize(HANDLE hFile); 00334 #else 00335 unsigned long __GetFileSize(FILE* hFile); 00336 #endif 00337 }; 00338 00342 class Exception { 00343 public: 00344 String Message; 00345 00346 Exception(String Message) { Exception::Message = Message; } 00347 void PrintMessage(); 00348 virtual ~Exception() {} 00349 }; 00350 00351 String libraryName(); 00352 String libraryVersion(); 00353 00354 } // namespace RIFF 00355 #endif // __RIFF_H__