/[svn]/linuxsampler/trunk/src/RIFF.cpp
ViewVC logotype

Contents of /linuxsampler/trunk/src/RIFF.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 9 - (show annotations) (download)
Wed Nov 5 14:47:10 2003 UTC (15 years, 9 months ago) by schoenebeck
File size: 25016 byte(s)
* transition from plain Makefile to autotools, source files moved to src/
* configure.in: added test for x86 architecture
* src/voice.h: x86 specific asm optimization for double to int casts only
  if compiling for x86 architecture

1 /***************************************************************************
2 * *
3 * libgig - C++ cross-platform Gigasampler format file loader library *
4 * *
5 * Copyright (C) 2003 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 #if 1
24 #include "RIFF.h"
25
26 namespace RIFF {
27
28 // *************** Chunk **************
29 // *
30
31 Chunk::Chunk() {
32 #if DEBUG
33 std::cout << "Chunk::Chunk()" << std::endl;
34 #endif // DEBUG
35 ulPos = 0;
36 pParent = NULL;
37 pChunkData = NULL;
38 }
39
40 #if POSIX
41 Chunk::Chunk(int hFile, unsigned long StartPos, bool EndianNative, List* Parent) {
42 #else
43 Chunk::Chunk(FILE* hFile, unsigned long StartPos, bool EndianNative, List* Parent) {
44 #endif // POSIX
45 #if DEBUG
46 std::cout << "Chunk::Chunk(FILE,ulong,bool,List*),StartPos=" << StartPos << std::endl;
47 #endif // DEBUG
48 Chunk::hFile = hFile;
49 ulStartPos = StartPos + CHUNK_HEADER_SIZE;
50 bEndianNative = EndianNative;
51 pParent = Parent;
52 ulPos = 0;
53 pChunkData = NULL;
54 ReadHeader(StartPos);
55 }
56
57 Chunk::~Chunk() {
58 if (pChunkData) delete[] pChunkData;
59 }
60
61 void Chunk::ReadHeader(unsigned long fPos) {
62 #if DEBUG
63 std::cout << "Chunk::Readheader(" << fPos << ") ";
64 #endif // DEBUG
65 #if POSIX
66 if (lseek(hFile, fPos, SEEK_SET) != -1) {
67 read(hFile, &ChunkID, 4);
68 read(hFile, &ChunkSize, 4);
69 #else
70 if (!fseek(hFile, fPos, SEEK_SET)) {
71 fread(&ChunkID, 4, 1, hFile);
72 fread(&ChunkSize, 4, 1, hFile);
73 #endif // POSIX
74 #if DEBUG
75 std::cout << "ckID=" << convertToString(ChunkID) << " ";
76 std::cout << "ckSize=" << ChunkSize << std::endl;
77 #endif // DEBUG
78 #if WORDS_BIGENDIAN
79 if (ChunkID == CHUNK_ID_RIFF) {
80 bEndianNative = false;
81 }
82 #else // little endian
83 if (ChunkID == CHUNK_ID_RIFX) {
84 bEndianNative = false;
85 ChunkID = CHUNK_ID_RIFF;
86 }
87 #endif // WORDS_BIGENDIAN
88 if (!bEndianNative) {
89 swapBytes_32(&ChunkID);
90 swapBytes_32(&ChunkSize);
91 }
92 }
93 }
94
95 String Chunk::GetChunkIDString() {
96 return convertToString(ChunkID);
97 }
98
99 unsigned long Chunk::SetPos(unsigned long Where, stream_whence_t Whence) {
100 #if DEBUG
101 std::cout << "Chunk::SetPos(ulong)" << std::endl;
102 #endif // DEBUG
103 switch (Whence) {
104 case stream_curpos:
105 ulPos += Where;
106 break;
107 case stream_end:
108 ulPos = ChunkSize - 1 - Where;
109 break;
110 case stream_backward:
111 ulPos -= Where;
112 break;
113 case stream_start: default:
114 ulPos = Where;
115 break;
116 }
117 if (ulPos > ChunkSize) ulPos = ChunkSize;
118 return ulPos;
119 }
120
121 unsigned long Chunk::RemainingBytes() {
122 #if DEBUG
123 std::cout << "Chunk::Remainingbytes()=" << ChunkSize - ulPos << std::endl;
124 #endif // DEBUG
125 return ChunkSize - ulPos;
126 }
127
128 stream_state_t Chunk::GetState() {
129 #if DEBUG
130 std::cout << "Chunk::GetState()" << std::endl;
131 #endif // DEBUG
132 #if POSIX
133 if (hFile == 0) return stream_closed;
134 #else
135 if (hFile == NULL) return stream_closed;
136 #endif // POSIX
137 if (ulPos < ChunkSize) return stream_ready;
138 else return stream_end_reached;
139 }
140
141 /**
142 * Reads \a WordCount number of data words with given \a WordSize and
143 * copies it into a buffer pointed by \a pData. The buffer has to be
144 * allocated and be sure to provide the correct \a WordSize, as this
145 * will be important and taken into account for eventual endian
146 * correction (swapping of bytes due to different native byte order of
147 * a system). The position within the chunk will automatically be
148 * incremented.
149 *
150 * @param pData destination buffer
151 * @param WordCount number of data words to read
152 * @param WordSize size of each data word to read
153 * @returns number of successfully read data words or 0 if end
154 * of file reached or error occured
155 */
156 unsigned long Chunk::Read(void* pData, unsigned long WordCount, unsigned long WordSize) {
157 #if DEBUG
158 std::cout << "Chunk::Read(void*,ulong,ulong)" << std::endl;
159 #endif // DEBUG
160 if (ChunkSize - ulPos <= 0) return 0;
161 if (ulPos + WordCount * WordSize >= ChunkSize) WordCount = (ChunkSize - ulPos) / WordSize;
162 #if POSIX
163 if (lseek(hFile, ulStartPos + ulPos, SEEK_SET) < 0) return 0;
164 unsigned long readWords = read(hFile, pData, WordCount * WordSize);
165 if (readWords < 1) return 0;
166 readWords /= WordSize;
167 #else // standard C functions
168 if (fseek(hFile, ulStartPos + ulPos, SEEK_SET)) return 0;
169 unsigned long readWords = fread(pData, WordSize, WordCount, hFile);
170 #endif // POSIX
171 if (!bEndianNative && WordSize != 1) {
172 switch (WordSize) {
173 case 2:
174 for (unsigned long iWord = 0; iWord < readWords; iWord++)
175 swapBytes_16((uint16_t*) pData + iWord);
176 break;
177 case 4:
178 for (unsigned long iWord = 0; iWord < readWords; iWord++)
179 swapBytes_32((uint32_t*) pData + iWord);
180 break;
181 default:
182 for (unsigned long iWord = 0; iWord < readWords; iWord++)
183 swapBytes((uint8_t*) pData + iWord * WordSize, WordSize);
184 break;
185 }
186 }
187 SetPos(readWords * WordSize, stream_curpos);
188 return readWords;
189 }
190
191 /** Just an internal wrapper for the main <i>Read()</i> method with additional Exception throwing on errors. */
192 unsigned long Chunk::ReadSceptical(void* pData, unsigned long WordCount, unsigned long WordSize) {
193 unsigned long readWords = Read(pData, WordCount, WordSize);
194 if (readWords != WordCount) throw RIFF::Exception("End of chunk data reached.");
195 return readWords;
196 }
197
198 /**
199 * Reads \a WordCount number of 8 Bit signed integer words and copies it
200 * into the buffer pointed by \a pData. The buffer has to be allocated.
201 * The position within the chunk will automatically be incremented.
202 *
203 * @param pData destination buffer
204 * @param WordCount number of 8 Bit signed integers to read
205 * @returns number of read integers
206 * @throws RIFF::Exception if an error occured or less than
207 * \a WordCount integers could be read!
208 */
209 unsigned long Chunk::ReadInt8(int8_t* pData, unsigned long WordCount) {
210 #if DEBUG
211 std::cout << "Chunk::ReadInt8(int8_t*,ulong)" << std::endl;
212 #endif // DEBUG
213 return ReadSceptical(pData, WordCount, 1);
214 }
215
216 /**
217 * Reads \a WordCount number of 8 Bit unsigned integer words and copies
218 * it into the buffer pointed by \a pData. The buffer has to be
219 * allocated. The position within the chunk will automatically be
220 * incremented.
221 *
222 * @param pData destination buffer
223 * @param WordCount number of 8 Bit unsigned integers to read
224 * @returns number of read integers
225 * @throws RIFF::Exception if an error occured or less than
226 * \a WordCount integers could be read!
227 */
228 unsigned long Chunk::ReadUint8(uint8_t* pData, unsigned long WordCount) {
229 #if DEBUG
230 std::cout << "Chunk::ReadUint8(uint8_t*,ulong)" << std::endl;
231 #endif // DEBUG
232 return ReadSceptical(pData, WordCount, 1);
233 }
234
235 /**
236 * Reads \a WordCount number of 16 Bit signed integer words and copies
237 * it into the buffer pointed by \a pData. The buffer has to be
238 * allocated. Endian correction will automatically be done if needed.
239 * The position within the chunk will automatically be incremented.
240 *
241 * @param pData destination buffer
242 * @param WordCount number of 16 Bit signed integers to read
243 * @returns number of read integers
244 * @throws RIFF::Exception if an error occured or less than
245 * \a WordCount integers could be read!
246 */
247 unsigned long Chunk::ReadInt16(int16_t* pData, unsigned long WordCount) {
248 #if DEBUG
249 std::cout << "Chunk::ReadInt16(int16_t*,ulong)" << std::endl;
250 #endif // DEBUG
251 return ReadSceptical(pData, WordCount, 2);
252 }
253
254 /**
255 * Reads \a WordCount number of 16 Bit unsigned integer words and copies
256 * it into the buffer pointed by \a pData. The buffer has to be
257 * allocated. Endian correction will automatically be done if needed.
258 * The position within the chunk will automatically be incremented.
259 *
260 * @param pData destination buffer
261 * @param WordCount number of 8 Bit unsigned integers to read
262 * @returns number of read integers
263 * @throws RIFF::Exception if an error occured or less than
264 * \a WordCount integers could be read!
265 */
266 unsigned long Chunk::ReadUint16(uint16_t* pData, unsigned long WordCount) {
267 #if DEBUG
268 std::cout << "Chunk::ReadUint16(uint16_t*,ulong)" << std::endl;
269 #endif // DEBUG
270 return ReadSceptical(pData, WordCount, 2);
271 }
272
273 /**
274 * Reads \a WordCount number of 32 Bit signed integer words and copies
275 * it into the buffer pointed by \a pData. The buffer has to be
276 * allocated. Endian correction will automatically be done if needed.
277 * The position within the chunk will automatically be incremented.
278 *
279 * @param pData destination buffer
280 * @param WordCount number of 32 Bit signed integers to read
281 * @returns number of read integers
282 * @throws RIFF::Exception if an error occured or less than
283 * \a WordCount integers could be read!
284 */
285 unsigned long Chunk::ReadInt32(int32_t* pData, unsigned long WordCount) {
286 #if DEBUG
287 std::cout << "Chunk::ReadInt32(int32_t*,ulong)" << std::endl;
288 #endif // DEBUG
289 return ReadSceptical(pData, WordCount, 4);
290 }
291
292 /**
293 * Reads \a WordCount number of 32 Bit unsigned integer words and copies
294 * it into the buffer pointed by \a pData. The buffer has to be
295 * allocated. Endian correction will automatically be done if needed.
296 * The position within the chunk will automatically be incremented.
297 *
298 * @param pData destination buffer
299 * @param WordCount number of 32 Bit unsigned integers to read
300 * @returns number of read integers
301 * @throws RIFF::Exception if an error occured or less than
302 * \a WordCount integers could be read!
303 */
304 unsigned long Chunk::ReadUint32(uint32_t* pData, unsigned long WordCount) {
305 #if DEBUG
306 std::cout << "Chunk::ReadUint32(uint32_t*,ulong)" << std::endl;
307 #endif // DEBUG
308 return ReadSceptical(pData, WordCount, 4);
309 }
310
311 /**
312 * Reads one 8 Bit signed integer word and increments the position within
313 * the chunk.
314 *
315 * @returns read integer word
316 * @throws RIFF::Exception if an error occured
317 */
318 int8_t Chunk::ReadInt8() {
319 #if DEBUG
320 std::cout << "Chunk::ReadInt8()" << std::endl;
321 #endif // DEBUG
322 int8_t word;
323 ReadSceptical(&word,1,1);
324 return word;
325 }
326
327 /**
328 * Reads one 8 Bit unsigned integer word and increments the position
329 * within the chunk.
330 *
331 * @returns read integer word
332 * @throws RIFF::Exception if an error occured
333 */
334 uint8_t Chunk::ReadUint8() {
335 #if DEBUG
336 std::cout << "Chunk::ReadUint8()" << std::endl;
337 #endif // DEBUG
338 uint8_t word;
339 ReadSceptical(&word,1,1);
340 return word;
341 }
342
343 /**
344 * Reads one 16 Bit signed integer word and increments the position
345 * within the chunk. Endian correction will automatically be done if
346 * needed.
347 *
348 * @returns read integer word
349 * @throws RIFF::Exception if an error occured
350 */
351 int16_t Chunk::ReadInt16() {
352 #if DEBUG
353 std::cout << "Chunk::ReadInt16()" << std::endl;
354 #endif // DEBUG
355 int16_t word;
356 ReadSceptical(&word,1,2);
357 return word;
358 }
359
360 /**
361 * Reads one 16 Bit unsigned integer word and increments the position
362 * within the chunk. Endian correction will automatically be done if
363 * needed.
364 *
365 * @returns read integer word
366 * @throws RIFF::Exception if an error occured
367 */
368 uint16_t Chunk::ReadUint16() {
369 #if DEBUG
370 std::cout << "Chunk::ReadUint16()" << std::endl;
371 #endif // DEBUG
372 uint16_t word;
373 ReadSceptical(&word,1,2);
374 return word;
375 }
376
377 /**
378 * Reads one 32 Bit signed integer word and increments the position
379 * within the chunk. Endian correction will automatically be done if
380 * needed.
381 *
382 * @returns read integer word
383 * @throws RIFF::Exception if an error occured
384 */
385 int32_t Chunk::ReadInt32() {
386 #if DEBUG
387 std::cout << "Chunk::ReadInt32()" << std::endl;
388 #endif // DEBUG
389 int32_t word;
390 ReadSceptical(&word,1,4);
391 return word;
392 }
393
394 /**
395 * Reads one 32 Bit unsigned integer word and increments the position
396 * within the chunk. Endian correction will automatically be done if
397 * needed.
398 *
399 * @returns read integer word
400 * @throws RIFF::Exception if an error occured
401 */
402 uint32_t Chunk::ReadUint32() {
403 #if DEBUG
404 std::cout << "Chunk::ReadUint32()" << std::endl;
405 #endif // DEBUG
406 uint32_t word;
407 ReadSceptical(&word,1,4);
408 return word;
409 }
410
411 void* Chunk::LoadChunkData() {
412 if (!pChunkData) {
413 #if POSIX
414 if (lseek(hFile, ulStartPos, SEEK_SET) == -1) return NULL;
415 pChunkData = new uint8_t[GetSize()];
416 if (!pChunkData) return NULL;
417 unsigned long readWords = read(hFile, pChunkData, GetSize());
418 #else
419 if (fseek(hFile, ulStartPos, SEEK_SET)) return NULL;
420 pChunkData = new uint8_t[GetSize()];
421 if (!pChunkData) return NULL;
422 unsigned long readWords = fread(pChunkData, 1, GetSize(), hFile);
423 #endif // POSIX
424 if (readWords != GetSize()) {
425 delete[] pChunkData;
426 return (pChunkData = NULL);
427 }
428 }
429 return pChunkData;
430 }
431
432 void Chunk::ReleaseChunkData() {
433 if (pChunkData) {
434 delete[] pChunkData;
435 pChunkData = NULL;
436 }
437 }
438
439
440
441 // *************** List ***************
442 // *
443
444 List::List() : Chunk() {
445 #if DEBUG
446 std::cout << "List::List()" << std::endl;
447 #endif // DEBUG
448 pSubChunks = NULL;
449 pSubChunksMap = NULL;
450 }
451
452 #if POSIX
453 List::List(int hFile, unsigned long StartPos, bool EndianNative, List* Parent)
454 #else
455 List::List(FILE* hFile, unsigned long StartPos, bool EndianNative, List* Parent)
456 #endif // POSIX
457 : Chunk(hFile, StartPos, EndianNative, Parent) {
458 #if DEBUG
459 std::cout << "List::List(FILE*,ulong,bool,List*)" << std::endl;
460 #endif // DEBUG
461 pSubChunks = NULL;
462 pSubChunksMap = NULL;
463 ReadHeader(StartPos);
464 ulStartPos = StartPos + LIST_HEADER_SIZE;
465 }
466
467 List::~List() {
468 #if DEBUG
469 std::cout << "List::~List()" << std::endl;
470 #endif // DEBUG
471 if (pSubChunks) {
472 ChunkList::iterator iter = pSubChunks->begin();
473 ChunkList::iterator end = pSubChunks->end();
474 while (iter != end) {
475 delete *iter;
476 iter++;
477 }
478 delete pSubChunks;
479 }
480 if (pSubChunksMap) delete pSubChunksMap;
481 }
482
483 Chunk* List::GetSubChunk(uint32_t ChunkID) {
484 #if DEBUG
485 std::cout << "List::GetSubChunk(uint32_t)" << std::endl;
486 #endif // DEBUG
487 if (!pSubChunksMap) LoadSubChunks();
488 return (*pSubChunksMap)[ChunkID];
489 }
490
491 List* List::GetSubList(uint32_t ListType) {
492 #if DEBUG
493 std::cout << "List::GetSubList(uint32_t)" << std::endl;
494 #endif // DEBUG
495 if (!pSubChunks) LoadSubChunks();
496 ChunkList::iterator iter = pSubChunks->begin();
497 ChunkList::iterator end = pSubChunks->end();
498 while (iter != end) {
499 if ((*iter)->GetChunkID() == CHUNK_ID_LIST) {
500 List* l = (List*) *iter;
501 if (l->GetListType() == ListType) return l;
502 }
503 iter++;
504 }
505 return NULL;
506 }
507
508 Chunk* List::GetFirstSubChunk() {
509 #if DEBUG
510 std::cout << "List::GetFirstSubChunk()" << std::endl;
511 #endif // DEBUG
512 if (!pSubChunks) LoadSubChunks();
513 ChunksIterator = pSubChunks->begin();
514 return (ChunksIterator != pSubChunks->end()) ? *ChunksIterator : NULL;
515 }
516
517 Chunk* List::GetNextSubChunk() {
518 #if DEBUG
519 std::cout << "List::GetNextSubChunk()" << std::endl;
520 #endif // DEBUG
521 if (!pSubChunks) return NULL;
522 ChunksIterator++;
523 return (ChunksIterator != pSubChunks->end()) ? *ChunksIterator : NULL;
524 }
525
526 List* List::GetFirstSubList() {
527 #if DEBUG
528 std::cout << "List::GetFirstSubList()" << std::endl;
529 #endif // DEBUG
530 if (!pSubChunks) LoadSubChunks();
531 ListIterator = pSubChunks->begin();
532 ChunkList::iterator end = pSubChunks->end();
533 while (ListIterator != end) {
534 if ((*ListIterator)->GetChunkID() == CHUNK_ID_LIST) return (List*) *ListIterator;
535 ListIterator++;
536 }
537 return NULL;
538 }
539
540 List* List::GetNextSubList() {
541 #if DEBUG
542 std::cout << "List::GetNextSubList()" << std::endl;
543 #endif // DEBUG
544 if (!pSubChunks) return NULL;
545 if (ListIterator == pSubChunks->end()) return NULL;
546 ListIterator++;
547 ChunkList::iterator end = pSubChunks->end();
548 while (ListIterator != end) {
549 if ((*ListIterator)->GetChunkID() == CHUNK_ID_LIST) return (List*) *ListIterator;
550 ListIterator++;
551 }
552 return NULL;
553 }
554
555 unsigned int List::CountSubChunks() {
556 if (!pSubChunks) LoadSubChunks();
557 return pSubChunks->size();
558 }
559
560 unsigned int List::CountSubChunks(uint32_t ChunkID) {
561 unsigned int result = 0;
562 if (!pSubChunks) LoadSubChunks();
563 ChunkList::iterator iter = pSubChunks->begin();
564 ChunkList::iterator end = pSubChunks->end();
565 while (iter != end) {
566 if ((*iter)->GetChunkID() == ChunkID) {
567 result++;
568 }
569 iter++;
570 }
571 return result;
572 }
573
574 unsigned int List::CountSubLists() {
575 return CountSubChunks(CHUNK_ID_LIST);
576 }
577
578 unsigned int List::CountSubLists(uint32_t ListType) {
579 unsigned int result = 0;
580 if (!pSubChunks) LoadSubChunks();
581 ChunkList::iterator iter = pSubChunks->begin();
582 ChunkList::iterator end = pSubChunks->end();
583 while (iter != end) {
584 if ((*iter)->GetChunkID() == CHUNK_ID_LIST) {
585 List* l = (List*) *iter;
586 if (l->GetListType() == ListType) result++;
587 }
588 iter++;
589 }
590 return result;
591 }
592
593 void List::ReadHeader(unsigned long fPos) {
594 #if DEBUG
595 std::cout << "List::Readheader(ulong) ";
596 #endif // DEBUG
597 Chunk::ReadHeader(fPos);
598 ChunkSize -= 4;
599 #if POSIX
600 lseek(hFile, fPos + CHUNK_HEADER_SIZE, SEEK_SET);
601 read(hFile, &ListType, 4);
602 #else
603 fseek(hFile, fPos + CHUNK_HEADER_SIZE, SEEK_SET);
604 fread(&ListType, 4, 1, hFile);
605 #endif // POSIX
606 #if DEBUG
607 std::cout << "listType=" << convertToString(ListType) << std::endl;
608 #endif // DEBUG
609 if (!bEndianNative) {
610 swapBytes_32(&ListType);
611 }
612 }
613
614 void List::LoadSubChunks() {
615 #if DEBUG
616 std::cout << "List::LoadSubChunks()";
617 #endif // DEBUG
618 if (!pSubChunks) {
619 pSubChunks = new ChunkList();
620 pSubChunksMap = new ChunkMap();
621 while (RemainingBytes() >= CHUNK_HEADER_SIZE) {
622 Chunk* ck;
623 uint32_t ckid = ReadUint32();
624 #if DEBUG
625 std::cout << " ckid=" << convertToString(ckid) << std::endl;
626 #endif // DEBUG
627 if (ckid == CHUNK_ID_LIST) {
628 ck = new RIFF::List(hFile, ulStartPos + ulPos - 4, bEndianNative, this);
629 SetPos(ck->GetSize() + LIST_HEADER_SIZE - 4, RIFF::stream_curpos);
630 }
631 else { // simple chunk
632 ck = new RIFF::Chunk(hFile, ulStartPos + ulPos - 4, bEndianNative, this);
633 SetPos(ck->GetSize() + CHUNK_HEADER_SIZE - 4, RIFF::stream_curpos);
634 }
635 pSubChunks->push_back(ck);
636 (*pSubChunksMap)[ckid] = ck;
637 if (GetPos() % 2 != 0) SetPos(1, RIFF::stream_curpos); // jump over pad byte
638 }
639 }
640 }
641
642 String List::GetListTypeString() {
643 return convertToString(ListType);
644 }
645
646
647
648 // *************** File ***************
649 // *
650
651 File::File(const String& path) : List() {
652 #if DEBUG
653 std::cout << "File::File("<<path<<")" << std::endl;
654 #endif // DEBUG
655 bEndianNative = true;
656 #if POSIX
657 hFile = open(path.c_str(), O_RDONLY | O_NONBLOCK);
658 if (hFile <= 0) {
659 hFile = 0;
660 throw RIFF::Exception("Can't open \"" + path + "\"");
661 }
662 #else
663 hFile = fopen(path.c_str(), "rb");
664 if (!hFile) throw RIFF::Exception("Can't open \"" + path + "\"");
665 #endif // POSIX
666 ulStartPos = RIFF_HEADER_SIZE;
667 ReadHeader(0);
668 if (ChunkID != CHUNK_ID_RIFF) {
669 throw RIFF::Exception("Not a RIFF file");
670 }
671 }
672
673 File::~File() {
674 #if DEBUG
675 std::cout << "File::~File()" << std::endl;
676 #endif // DEBUG
677 #if POSIX
678 if (hFile) close(hFile);
679 #else
680 if (hFile) fclose(hFile);
681 #endif // POSIX
682 }
683
684 unsigned long File::GetFileSize() {
685 #if POSIX
686 struct stat filestat;
687 fstat(hFile, &filestat);
688 long size = filestat.st_size;
689 #else // standard C functions
690 long curpos = ftell(hFile);
691 fseek(hFile, 0, SEEK_END);
692 long size = ftell(hFile);
693 fseek(hFile, curpos, SEEK_SET);
694 #endif // POSIX
695 return size;
696 }
697
698
699
700 // *************** Exception ***************
701 // *
702
703 void Exception::PrintMessage() {
704 std::cout << "RIFF::Exception: " << Message << std::endl;
705 }
706
707 } // namespace RIFF
708 #endif

  ViewVC Help
Powered by ViewVC