/[svn]/libgig/trunk/src/RIFF.h
ViewVC logotype

Contents of /libgig/trunk/src/RIFF.h

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1678 - (show annotations) (download) (as text)
Sun Feb 10 16:07:22 2008 UTC (16 years, 2 months ago) by persson
File MIME type: text/x-c++hdr
File size: 14151 byte(s)
* bugfix: saving to the same file after the file size had been
  increased made the file corrupt (#82)
* bugfix: removed another iterator invalidation in DeleteSample
* changed the functions for midi rules, to get rid of the iterator

1 /***************************************************************************
2 * *
3 * libgig - C++ cross-platform Gigasampler format file access library *
4 * *
5 * Copyright (C) 2003-2007 by Christian Schoenebeck *
6 * <cuse@users.sourceforge.net> *
7 * *
8 * This library is free software; you can redistribute it and/or modify *
9 * it under the terms of the GNU General Public License as published by *
10 * the Free Software Foundation; either version 2 of the License, or *
11 * (at your option) any later version. *
12 * *
13 * This library is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this library; if not, write to the Free Software *
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21 * MA 02111-1307 USA *
22 ***************************************************************************/
23
24 #ifndef __RIFF_H__
25 #define __RIFF_H__
26
27 #ifdef WIN32
28 # define POSIX 0
29 #endif
30
31 #ifndef POSIX
32 # define POSIX 1
33 #endif
34
35 #ifndef DEBUG
36 # define DEBUG 0
37 #endif
38
39 #include <string>
40 #include <list>
41 #include <set>
42 #include <map>
43 #include <iostream>
44
45 #ifdef HAVE_CONFIG_H
46 # include <config.h>
47 #endif
48
49 #if POSIX
50 # include <sys/types.h>
51 # include <sys/stat.h>
52 # include <fcntl.h>
53 # include <unistd.h>
54 #endif // POSIX
55
56 #include <stdint.h>
57
58 #ifdef WIN32
59 # include <windows.h>
60 typedef unsigned int uint;
61 #endif // WIN32
62
63 #include <stdio.h>
64
65 #if WORDS_BIGENDIAN
66 # define CHUNK_ID_RIFF 0x52494646
67 # define CHUNK_ID_RIFX 0x52494658
68 # define CHUNK_ID_LIST 0x4C495354
69 #else // little endian
70 # define CHUNK_ID_RIFF 0x46464952
71 # define CHUNK_ID_RIFX 0x58464952
72 # define CHUNK_ID_LIST 0x5453494C
73 #endif // WORDS_BIGENDIAN
74
75 #define CHUNK_HEADER_SIZE 8
76 #define LIST_HEADER_SIZE 12
77 #define RIFF_HEADER_SIZE 12
78
79
80 /**
81 * @brief RIFF specific classes and definitions
82 *
83 * The Resource Interchange File Format (RIFF) is a generic tree-structured
84 * meta-format which stores data in so called "chunks". It can be compared
85 * to XML, but in contrast to XML, RIFF is entirely binary encoded, that is
86 * not ASCII based. RIFF is used as basis for many file formats like AVI,
87 * WAV, DLS and of course the Gigasampler file format. ;-)
88 *
89 * RIFF chunks can be seen as containers for data. There are two distinct
90 * types of chunks:
91 *
92 * - @e ordinary @e chunks are the leafs of the data tree which encapsulate
93 * the actual data of the file (i.e. the sample data of a .wav file)
94 *
95 * - @e list @e chunks are the nodes of the data tree which hold an
96 * arbitrary amount of subchunks (can be both, list chunks and/or ordinary
97 * chunks)
98 */
99 namespace RIFF {
100
101 /* just symbol prototyping */
102 class Chunk;
103 class List;
104 class File;
105
106 typedef std::string String;
107
108 /** Whether file stream is open in read or in read/write mode. */
109 typedef enum {
110 stream_mode_read = 0,
111 stream_mode_read_write = 1,
112 stream_mode_closed = 2
113 } stream_mode_t;
114
115 /** Current state of the file stream. */
116 typedef enum {
117 stream_ready = 0,
118 stream_end_reached = 1,
119 stream_closed = 2
120 } stream_state_t;
121
122 /** File stream position dependent to these relations. */
123 typedef enum {
124 stream_start = 0,
125 stream_curpos = 1,
126 stream_backward = 2,
127 stream_end = 3
128 } stream_whence_t;
129
130 /** Alignment of data bytes in memory (system dependant). */
131 typedef enum {
132 endian_little = 0,
133 endian_big = 1,
134 endian_native = 2
135 } endian_t;
136
137 /** @brief Ordinary RIFF Chunk
138 *
139 * Provides convenient methods to access data of ordinary RIFF chunks
140 * in general.
141 */
142 class Chunk {
143 public:
144 Chunk(File* pFile, unsigned long StartPos, List* Parent);
145 String GetChunkIDString();
146 uint32_t GetChunkID() { return ChunkID; }; ///< Chunk ID in unsigned integer representation.
147 List* GetParent() { return pParent; }; ///< Returns pointer to the chunk's parent list chunk.
148 unsigned long GetSize() { return CurrentChunkSize; }; ///< Chunk size in bytes (without header, thus the chunk data body)
149 unsigned long GetNewSize() { return NewChunkSize; }; ///< New chunk size if it was modified with Resize().
150 unsigned long GetPos() { return ulPos; }; ///< Position within the chunk data body
151 unsigned long GetFilePos() { return ulStartPos + ulPos; }; ///< Current, actual offset in file.
152 unsigned long SetPos(unsigned long Where, stream_whence_t Whence = stream_start);
153 unsigned long RemainingBytes();
154 stream_state_t GetState();
155 unsigned long Read(void* pData, unsigned long WordCount, unsigned long WordSize);
156 unsigned long ReadInt8(int8_t* pData, unsigned long WordCount = 1);
157 unsigned long ReadUint8(uint8_t* pData, unsigned long WordCount = 1);
158 unsigned long ReadInt16(int16_t* pData, unsigned long WordCount = 1);
159 unsigned long ReadUint16(uint16_t* pData, unsigned long WordCount = 1);
160 unsigned long ReadInt32(int32_t* pData, unsigned long WordCount = 1);
161 unsigned long ReadUint32(uint32_t* pData, unsigned long WordCount = 1);
162 int8_t ReadInt8();
163 uint8_t ReadUint8();
164 int16_t ReadInt16();
165 uint16_t ReadUint16();
166 int32_t ReadInt32();
167 uint32_t ReadUint32();
168 unsigned long Write(void* pData, unsigned long WordCount, unsigned long WordSize);
169 unsigned long WriteInt8(int8_t* pData, unsigned long WordCount = 1);
170 unsigned long WriteUint8(uint8_t* pData, unsigned long WordCount = 1);
171 unsigned long WriteInt16(int16_t* pData, unsigned long WordCount = 1);
172 unsigned long WriteUint16(uint16_t* pData, unsigned long WordCount = 1);
173 unsigned long WriteInt32(int32_t* pData, unsigned long WordCount = 1);
174 unsigned long WriteUint32(uint32_t* pData, unsigned long WordCount = 1);
175 void* LoadChunkData();
176 void ReleaseChunkData();
177 void Resize(int iNewSize);
178 virtual ~Chunk();
179 protected:
180 uint32_t ChunkID;
181 uint32_t CurrentChunkSize; /* in bytes */
182 uint32_t NewChunkSize; /* in bytes (if chunk was scheduled to be resized) */
183 List* pParent;
184 File* pFile;
185 unsigned long ulStartPos; /* actual position in file where chunk (without header) starts */
186 unsigned long ulPos; /* # of bytes from ulStartPos */
187 uint8_t* pChunkData;
188 unsigned long ulChunkDataSize;
189
190 Chunk(File* pFile);
191 Chunk(File* pFile, List* pParent, uint32_t uiChunkID, uint uiBodySize);
192 void ReadHeader(unsigned long fPos);
193 void WriteHeader(unsigned long fPos);
194 unsigned long ReadSceptical(void* pData, unsigned long WordCount, unsigned long WordSize);
195 inline void swapBytes_16(void* Word) {
196 uint8_t byteCache = *((uint8_t*) Word);
197 *((uint8_t*) Word) = *((uint8_t*) Word + 1);
198 *((uint8_t*) Word + 1) = byteCache;
199 }
200 inline void swapBytes_32(void* Word) {
201 uint8_t byteCache = *((uint8_t*) Word);
202 *((uint8_t*) Word) = *((uint8_t*) Word + 3);
203 *((uint8_t*) Word + 3) = byteCache;
204 byteCache = *((uint8_t*) Word + 1);
205 *((uint8_t*) Word + 1) = *((uint8_t*) Word + 2);
206 *((uint8_t*) Word + 2) = byteCache;
207 }
208 inline void swapBytes(void* Word, unsigned long WordSize) {
209 uint8_t byteCache;
210 unsigned long lo = 0, hi = WordSize - 1;
211 for (; lo < hi; hi--, lo++) {
212 byteCache = *((uint8_t*) Word + lo);
213 *((uint8_t*) Word + lo) = *((uint8_t*) Word + hi);
214 *((uint8_t*) Word + hi) = byteCache;
215 }
216 }
217 inline String convertToString(uint32_t word) {
218 String result;
219 for (int i = 0; i < 4; i++) {
220 uint8_t byte = *((uint8_t*)(&word) + i);
221 char c = byte;
222 result += c;
223 }
224 return result;
225 }
226 virtual unsigned long WriteChunk(unsigned long ulWritePos, unsigned long ulCurrentDataOffset);
227 virtual void __resetPos(); ///< Sets Chunk's read/write position to zero.
228
229 friend class List;
230 };
231
232 /** @brief RIFF List Chunk
233 *
234 * Provides convenient methods to access data of RIFF list chunks and
235 * their subchunks.
236 */
237 class List : public Chunk {
238 public:
239 List(File* pFile, unsigned long StartPos, List* Parent);
240 String GetListTypeString();
241 uint32_t GetListType() { return ListType; } ///< Returns unsigned integer representation of the list's ID
242 Chunk* GetSubChunk(uint32_t ChunkID);
243 List* GetSubList(uint32_t ListType);
244 Chunk* GetFirstSubChunk();
245 Chunk* GetNextSubChunk();
246 List* GetFirstSubList();
247 List* GetNextSubList();
248 unsigned int CountSubChunks();
249 unsigned int CountSubChunks(uint32_t ChunkID);
250 unsigned int CountSubLists();
251 unsigned int CountSubLists(uint32_t ListType);
252 Chunk* AddSubChunk(uint32_t uiChunkID, uint uiBodySize);
253 List* AddSubList(uint32_t uiListType);
254 void DeleteSubChunk(Chunk* pSubChunk);
255 void MoveSubChunk(Chunk* pSrc, Chunk* pDst);
256 virtual ~List();
257 protected:
258 typedef std::map<uint32_t, RIFF::Chunk*> ChunkMap;
259 typedef std::list<Chunk*> ChunkList;
260
261 uint32_t ListType;
262 ChunkList* pSubChunks;
263 ChunkMap* pSubChunksMap;
264 ChunkList::iterator ChunksIterator;
265 ChunkList::iterator ListIterator;
266
267 List(File* pFile);
268 List(File* pFile, List* pParent, uint32_t uiListID);
269 void ReadHeader(unsigned long fPos);
270 void WriteHeader(unsigned long fPos);
271 void LoadSubChunks();
272 void LoadSubChunksRecursively();
273 virtual unsigned long WriteChunk(unsigned long ulWritePos, unsigned long ulCurrentDataOffset);
274 virtual void __resetPos(); ///< Sets List Chunk's read/write position to zero and causes all sub chunks to do the same.
275 };
276
277 /** @brief RIFF File
278 *
279 * Handles arbitrary RIFF files and provides together with its base
280 * classes convenient methods to walk through, read and modify the
281 * file's RIFF tree.
282 */
283 class File : public List {
284 public:
285 File(uint32_t FileType);
286 File(const String& path);
287 stream_mode_t GetMode();
288 bool SetMode(stream_mode_t NewMode);
289 void SetByteOrder(endian_t Endian);
290 String GetFileName();
291 virtual void Save();
292 virtual void Save(const String& path);
293 virtual ~File();
294 protected:
295 #if POSIX
296 int hFileRead; ///< handle / descriptor for reading from file
297 int hFileWrite; ///< handle / descriptor for writing to (some) file
298 #elif defined(WIN32)
299 HANDLE hFileRead; ///< handle / descriptor for reading from file
300 HANDLE hFileWrite; ///< handle / descriptor for writing to (some) file
301 #else
302 FILE* hFileRead; ///< handle / descriptor for reading from file
303 FILE* hFileWrite; ///< handle / descriptor for writing to (some) file
304 #endif // POSIX
305 String Filename;
306 bool bEndianNative;
307
308 void LogAsResized(Chunk* pResizedChunk);
309 void UnlogResized(Chunk* pResizedChunk);
310 friend class Chunk;
311 friend class List;
312 private:
313 stream_mode_t Mode;
314 std::set<Chunk*> ResizedChunks; ///< All chunks which have been resized (enlarged / shortened).
315
316 unsigned long GetFileSize();
317 void ResizeFile(unsigned long ulNewSize);
318 #if POSIX
319 unsigned long __GetFileSize(int hFile);
320 #elif defined(WIN32)
321 unsigned long __GetFileSize(HANDLE hFile);
322 #else
323 unsigned long __GetFileSize(FILE* hFile);
324 #endif
325 };
326
327 /**
328 * Will be thrown whenever an error occurs while handling a RIFF file.
329 */
330 class Exception {
331 public:
332 String Message;
333
334 Exception(String Message) { Exception::Message = Message; };
335 void PrintMessage();
336 virtual ~Exception() {};
337 };
338
339 String libraryName();
340 String libraryVersion();
341
342 } // namespace RIFF
343 #endif // __RIFF_H__

  ViewVC Help
Powered by ViewVC