/[svn]/libgig/trunk/src/DLS.cpp
ViewVC logotype

Diff of /libgig/trunk/src/DLS.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 834 by persson, Mon Feb 6 17:58:21 2006 UTC revision 1416 by schoenebeck, Sun Oct 14 12:06:32 2007 UTC
# Line 1  Line 1 
1  /***************************************************************************  /***************************************************************************
2   *                                                                         *   *                                                                         *
3   *   libgig - C++ cross-platform Gigasampler format file loader library    *   *   libgig - C++ cross-platform Gigasampler format file access library    *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003-2005 by Christian Schoenebeck                      *   *   Copyright (C) 2003-2007 by Christian Schoenebeck                      *
6   *                              <cuse@users.sourceforge.net>               *   *                              <cuse@users.sourceforge.net>               *
7   *                                                                         *   *                                                                         *
8   *   This library is free software; you can redistribute it and/or modify  *   *   This library is free software; you can redistribute it and/or modify  *
# Line 25  Line 25 
25    
26  #include <time.h>  #include <time.h>
27    
28    #ifdef __APPLE__
29    #include <CoreFoundation/CFUUID.h>
30    #elif defined(HAVE_UUID_UUID_H)
31    #include <uuid/uuid.h>
32    #endif
33    
34  #include "helper.h"  #include "helper.h"
35    
36  // macros to decode connection transforms  // macros to decode connection transforms
# Line 45  Line 51 
51  #define CONN_TRANSFORM_INVERT_SRC_ENCODE(x)             ((x) ? 0x8000 : 0)  #define CONN_TRANSFORM_INVERT_SRC_ENCODE(x)             ((x) ? 0x8000 : 0)
52  #define CONN_TRANSFORM_INVERT_CTL_ENCODE(x)             ((x) ? 0x0200 : 0)  #define CONN_TRANSFORM_INVERT_CTL_ENCODE(x)             ((x) ? 0x0200 : 0)
53    
54  #define DRUM_TYPE_MASK                  0x00000001  #define DRUM_TYPE_MASK                  0x80000000
55    
56  #define F_RGN_OPTION_SELFNONEXCLUSIVE   0x0001  #define F_RGN_OPTION_SELFNONEXCLUSIVE   0x0001
57    
# Line 142  namespace DLS { Line 148  namespace DLS {
148          const int iEntrySize = 12; // 12 bytes per connection block          const int iEntrySize = 12; // 12 bytes per connection block
149          pArticulationCk->Resize(HeaderSize + Connections * iEntrySize);          pArticulationCk->Resize(HeaderSize + Connections * iEntrySize);
150          uint8_t* pData = (uint8_t*) pArticulationCk->LoadChunkData();          uint8_t* pData = (uint8_t*) pArticulationCk->LoadChunkData();
151          memccpy(&pData[0], &HeaderSize, 1, 2);          store16(&pData[0], HeaderSize);
152          memccpy(&pData[2], &Connections, 1, 2);          store16(&pData[2], Connections);
153          for (uint32_t i = 0; i < Connections; i++) {          for (uint32_t i = 0; i < Connections; i++) {
154              Connection::conn_block_t c = pConnections[i].ToConnBlock();              Connection::conn_block_t c = pConnections[i].ToConnBlock();
155              memccpy(&pData[HeaderSize + i * iEntrySize],     &c.source, 1, 2);              store16(&pData[HeaderSize + i * iEntrySize],     c.source);
156              memccpy(&pData[HeaderSize + i * iEntrySize + 2], &c.control, 1, 2);              store16(&pData[HeaderSize + i * iEntrySize + 2], c.control);
157              memccpy(&pData[HeaderSize + i * iEntrySize + 4], &c.destination, 1, 2);              store16(&pData[HeaderSize + i * iEntrySize + 4], c.destination);
158              memccpy(&pData[HeaderSize + i * iEntrySize + 6], &c.transform, 1, 2);              store16(&pData[HeaderSize + i * iEntrySize + 6], c.transform);
159              memccpy(&pData[HeaderSize + i * iEntrySize + 8], &c.scale, 1, 4);              store32(&pData[HeaderSize + i * iEntrySize + 8], c.scale);
160          }          }
161      }      }
162    
# Line 228  namespace DLS { Line 234  namespace DLS {
234    
235      /** @brief Constructor.      /** @brief Constructor.
236       *       *
237       * Initializes the info strings with values provided by a INFO list chunk.       * Initializes the info strings with values provided by an INFO list chunk.
238       *       *
239       * @param list - pointer to a list chunk which contains a INFO list chunk       * @param list - pointer to a list chunk which contains an INFO list chunk
240       */       */
241      Info::Info(RIFF::List* list) {      Info::Info(RIFF::List* list) {
242            pFixedStringLengths = NULL;
243          pResourceListChunk = list;          pResourceListChunk = list;
244          if (list) {          if (list) {
245              RIFF::List* lstINFO = list->GetSubList(LIST_TYPE_INFO);              RIFF::List* lstINFO = list->GetSubList(LIST_TYPE_INFO);
# Line 253  namespace DLS { Line 260  namespace DLS {
260                  LoadString(CHUNK_ID_ISRC, lstINFO, Source);                  LoadString(CHUNK_ID_ISRC, lstINFO, Source);
261                  LoadString(CHUNK_ID_ISRF, lstINFO, SourceForm);                  LoadString(CHUNK_ID_ISRF, lstINFO, SourceForm);
262                  LoadString(CHUNK_ID_ICMS, lstINFO, Commissioned);                  LoadString(CHUNK_ID_ICMS, lstINFO, Commissioned);
263                    LoadString(CHUNK_ID_ISBJ, lstINFO, Subject);
264              }              }
265          }          }
266      }      }
# Line 260  namespace DLS { Line 268  namespace DLS {
268      Info::~Info() {      Info::~Info() {
269      }      }
270    
271        /**
272         * Forces specific Info fields to be of a fixed length when being saved
273         * to a file. By default the respective RIFF chunk of an Info field
274         * will have a size analogue to its actual string length. With this
275         * method however this behavior can be overridden, allowing to force an
276         * arbitrary fixed size individually for each Info field.
277         *
278         * This method is used as a workaround for the gig format, not for DLS.
279         *
280         * @param lengths - NULL terminated array of string_length_t elements
281         */
282        void Info::SetFixedStringLengths(const string_length_t* lengths) {
283            pFixedStringLengths = lengths;
284        }
285    
286      /** @brief Load given INFO field.      /** @brief Load given INFO field.
287       *       *
288       * Load INFO field from INFO chunk with chunk ID \a ChunkID from INFO       * Load INFO field from INFO chunk with chunk ID \a ChunkID from INFO
# Line 267  namespace DLS { Line 290  namespace DLS {
290       */       */
291      void Info::LoadString(uint32_t ChunkID, RIFF::List* lstINFO, String& s) {      void Info::LoadString(uint32_t ChunkID, RIFF::List* lstINFO, String& s) {
292          RIFF::Chunk* ck = lstINFO->GetSubChunk(ChunkID);          RIFF::Chunk* ck = lstINFO->GetSubChunk(ChunkID);
293          if (ck) {          ::LoadString(ck, s); // function from helper.h
             // TODO: no check for ZSTR terminated strings yet  
             s.assign((char*) ck->LoadChunkData(), ck->GetSize());  
             ck->ReleaseChunkData();  
         }  
294      }      }
295    
296      /** @brief Apply given INFO field to the respective chunk.      /** @brief Apply given INFO field to the respective chunk.
# Line 290  namespace DLS { Line 309  namespace DLS {
309       * @param sDefault - default value       * @param sDefault - default value
310       */       */
311      void Info::SaveString(uint32_t ChunkID, RIFF::List* lstINFO, const String& s, const String& sDefault) {      void Info::SaveString(uint32_t ChunkID, RIFF::List* lstINFO, const String& s, const String& sDefault) {
312          RIFF::Chunk* ck = lstINFO->GetSubChunk(ChunkID);          int size = 0;
313          if (ck) { // if chunk exists already, use 's' as value          if (pFixedStringLengths) {
314              ck->Resize(s.size() + 1);              for (int i = 0 ; pFixedStringLengths[i].length ; i++) {
315              char* pData = (char*) ck->LoadChunkData();                  if (pFixedStringLengths[i].chunkId == ChunkID) {
316              memcpy(pData, s.c_str(), s.size() + 1);                      size = pFixedStringLengths[i].length;
317          } else if (s != "" || sDefault != "") { // create chunk                      break;
318              const String& sToSave = (s != "") ? s : sDefault;                  }
319              ck = lstINFO->AddSubChunk(ChunkID, sToSave.size() + 1);              }
             char* pData = (char*) ck->LoadChunkData();  
             memcpy(pData, sToSave.c_str(), sToSave.size() + 1);  
320          }          }
321            RIFF::Chunk* ck = lstINFO->GetSubChunk(ChunkID);
322            ::SaveString(ChunkID, ck, lstINFO, s, sDefault, size != 0, size); // function from helper.h
323      }      }
324    
325      /** @brief Update chunks with current info values.      /** @brief Update chunks with current info values.
# Line 313  namespace DLS { Line 332  namespace DLS {
332    
333          // make sure INFO list chunk exists          // make sure INFO list chunk exists
334          RIFF::List* lstINFO   = pResourceListChunk->GetSubList(LIST_TYPE_INFO);          RIFF::List* lstINFO   = pResourceListChunk->GetSubList(LIST_TYPE_INFO);
         if (!lstINFO) lstINFO = pResourceListChunk->AddSubList(LIST_TYPE_INFO);  
335    
336          // assemble default values in case the respective chunk is missing yet          String defaultName = "";
337          String defaultName = "NONAME";          String defaultCreationDate = "";
338          // get current date          String defaultSoftware = "";
339          time_t now = time(NULL);          String defaultComments = "";
340          tm* pNowBroken = localtime(&now);  
341          String defaultCreationDate = ToString(1900 + pNowBroken->tm_year) + "-" +          uint32_t resourceType = pResourceListChunk->GetListType();
342                                       ToString(pNowBroken->tm_mon + 1)  + "-" +  
343                                       ToString(pNowBroken->tm_mday);          if (!lstINFO) {
344          String defaultSoftware = libraryName() + " " + libraryVersion();              lstINFO = pResourceListChunk->AddSubList(LIST_TYPE_INFO);
345          String defaultComments = "Created with " + libraryName() + " " + libraryVersion();  
346                // assemble default values
347                defaultName = "NONAME";
348    
349                if (resourceType == RIFF_TYPE_DLS) {
350                    // get current date
351                    time_t now = time(NULL);
352                    tm* pNowBroken = localtime(&now);
353                    char buf[11];
354                    strftime(buf, 11, "%F", pNowBroken);
355                    defaultCreationDate = buf;
356    
357                    defaultComments = "Created with " + libraryName() + " " + libraryVersion();
358                }
359                if (resourceType == RIFF_TYPE_DLS || resourceType == LIST_TYPE_INS)
360                {
361                    defaultSoftware = libraryName() + " " + libraryVersion();
362                }
363            }
364    
365          // save values          // save values
366          SaveString(CHUNK_ID_INAM, lstINFO, Name, defaultName);  
367          SaveString(CHUNK_ID_IARL, lstINFO, ArchivalLocation, String(""));          SaveString(CHUNK_ID_IARL, lstINFO, ArchivalLocation, String(""));
368          SaveString(CHUNK_ID_ICRD, lstINFO, CreationDate, defaultCreationDate);          SaveString(CHUNK_ID_IART, lstINFO, Artists, String(""));
369            SaveString(CHUNK_ID_ICMS, lstINFO, Commissioned, String(""));
370          SaveString(CHUNK_ID_ICMT, lstINFO, Comments, defaultComments);          SaveString(CHUNK_ID_ICMT, lstINFO, Comments, defaultComments);
         SaveString(CHUNK_ID_IPRD, lstINFO, Product, String(""));  
371          SaveString(CHUNK_ID_ICOP, lstINFO, Copyright, String(""));          SaveString(CHUNK_ID_ICOP, lstINFO, Copyright, String(""));
372          SaveString(CHUNK_ID_IART, lstINFO, Artists, String(""));          SaveString(CHUNK_ID_ICRD, lstINFO, CreationDate, defaultCreationDate);
373            SaveString(CHUNK_ID_IENG, lstINFO, Engineer, String(""));
374          SaveString(CHUNK_ID_IGNR, lstINFO, Genre, String(""));          SaveString(CHUNK_ID_IGNR, lstINFO, Genre, String(""));
375          SaveString(CHUNK_ID_IKEY, lstINFO, Keywords, String(""));          SaveString(CHUNK_ID_IKEY, lstINFO, Keywords, String(""));
         SaveString(CHUNK_ID_IENG, lstINFO, Engineer, String(""));  
         SaveString(CHUNK_ID_ITCH, lstINFO, Technician, String(""));  
         SaveString(CHUNK_ID_ISFT, lstINFO, Software, defaultSoftware);  
376          SaveString(CHUNK_ID_IMED, lstINFO, Medium, String(""));          SaveString(CHUNK_ID_IMED, lstINFO, Medium, String(""));
377            SaveString(CHUNK_ID_INAM, lstINFO, Name, defaultName);
378            SaveString(CHUNK_ID_IPRD, lstINFO, Product, String(""));
379            SaveString(CHUNK_ID_ISBJ, lstINFO, Subject, String(""));
380            SaveString(CHUNK_ID_ISFT, lstINFO, Software, defaultSoftware);
381          SaveString(CHUNK_ID_ISRC, lstINFO, Source, String(""));          SaveString(CHUNK_ID_ISRC, lstINFO, Source, String(""));
382          SaveString(CHUNK_ID_ISRF, lstINFO, SourceForm, String(""));          SaveString(CHUNK_ID_ISRF, lstINFO, SourceForm, String(""));
383          SaveString(CHUNK_ID_ICMS, lstINFO, Commissioned, String(""));          SaveString(CHUNK_ID_ITCH, lstINFO, Technician, String(""));
384      }      }
385    
386    
# Line 391  namespace DLS { Line 429  namespace DLS {
429       */       */
430      void Resource::UpdateChunks() {      void Resource::UpdateChunks() {
431          pInfo->UpdateChunks();          pInfo->UpdateChunks();
432          //TODO: save DLSID  
433            if (pDLSID) {
434                // make sure 'dlid' chunk exists
435                RIFF::Chunk* ckDLSID = pResourceList->GetSubChunk(CHUNK_ID_DLID);
436                if (!ckDLSID) ckDLSID = pResourceList->AddSubChunk(CHUNK_ID_DLID, 16);
437                uint8_t* pData = (uint8_t*)ckDLSID->LoadChunkData();
438                // update 'dlid' chunk
439                store32(&pData[0], pDLSID->ulData1);
440                store16(&pData[4], pDLSID->usData2);
441                store16(&pData[6], pDLSID->usData3);
442                memcpy(&pData[8], pDLSID->abData, 8);
443            }
444      }      }
445    
446        /**
447         * Generates a new DLSID for the resource.
448         */
449        void Resource::GenerateDLSID() {
450    #if defined(WIN32) || defined(__APPLE__) || defined(HAVE_UUID_GENERATE)
451    
452            if (!pDLSID) pDLSID = new dlsid_t;
453    
454    #ifdef WIN32
455    
456            UUID uuid;
457            UuidCreate(&uuid);
458            pDLSID->ulData1 = uuid.Data1;
459            pDLSID->usData2 = uuid.Data2;
460            pDLSID->usData3 = uuid.Data3;
461            memcpy(pDLSID->abData, uuid.Data4, 8);
462    
463    #elif defined(__APPLE__)
464    
465            CFUUIDRef uuidRef = CFUUIDCreate(NULL);
466            CFUUIDBytes uuid = CFUUIDGetUUIDBytes(uuidRef);
467            CFRelease(uuidRef);
468            pDLSID->ulData1 = uuid.byte0 | uuid.byte1 << 8 | uuid.byte2 << 16 | uuid.byte3 << 24;
469            pDLSID->usData2 = uuid.byte4 | uuid.byte5 << 8;
470            pDLSID->usData3 = uuid.byte6 | uuid.byte7 << 8;
471            pDLSID->abData[0] = uuid.byte8;
472            pDLSID->abData[1] = uuid.byte9;
473            pDLSID->abData[2] = uuid.byte10;
474            pDLSID->abData[3] = uuid.byte11;
475            pDLSID->abData[4] = uuid.byte12;
476            pDLSID->abData[5] = uuid.byte13;
477            pDLSID->abData[6] = uuid.byte14;
478            pDLSID->abData[7] = uuid.byte15;
479    #else
480            uuid_t uuid;
481            uuid_generate(uuid);
482            pDLSID->ulData1 = uuid[0] | uuid[1] << 8 | uuid[2] << 16 | uuid[3] << 24;
483            pDLSID->usData2 = uuid[4] | uuid[5] << 8;
484            pDLSID->usData3 = uuid[6] | uuid[7] << 8;
485            memcpy(pDLSID->abData, &uuid[8], 8);
486    #endif
487    #endif
488        }
489    
490    
491  // *************** Sampler ***************  // *************** Sampler ***************
# Line 410  namespace DLS { Line 502  namespace DLS {
502              SamplerOptions = wsmp->ReadUint32();              SamplerOptions = wsmp->ReadUint32();
503              SampleLoops    = wsmp->ReadUint32();              SampleLoops    = wsmp->ReadUint32();
504          } else { // 'wsmp' chunk missing          } else { // 'wsmp' chunk missing
505              uiHeaderSize   = 0;              uiHeaderSize   = 20;
506              UnityNote      = 64;              UnityNote      = 60;
507              FineTune       = 0; // +- 0 cents              FineTune       = 0; // +- 0 cents
508              Gain           = 0; // 0 dB              Gain           = 0; // 0 dB
509              SamplerOptions = F_WSMP_NO_COMPRESSION;              SamplerOptions = F_WSMP_NO_COMPRESSION;
# Line 435  namespace DLS { Line 527  namespace DLS {
527          if (pSampleLoops) delete[] pSampleLoops;          if (pSampleLoops) delete[] pSampleLoops;
528      }      }
529    
530        void Sampler::SetGain(int32_t gain) {
531            Gain = gain;
532        }
533    
534      /**      /**
535       * Apply all sample player options to the respective RIFF chunk. You       * Apply all sample player options to the respective RIFF chunk. You
536       * have to call File::Save() to make changes persistent.       * have to call File::Save() to make changes persistent.
# Line 442  namespace DLS { Line 538  namespace DLS {
538      void Sampler::UpdateChunks() {      void Sampler::UpdateChunks() {
539          // make sure 'wsmp' chunk exists          // make sure 'wsmp' chunk exists
540          RIFF::Chunk* wsmp = pParentList->GetSubChunk(CHUNK_ID_WSMP);          RIFF::Chunk* wsmp = pParentList->GetSubChunk(CHUNK_ID_WSMP);
541            int wsmpSize = uiHeaderSize + SampleLoops * 16;
542          if (!wsmp) {          if (!wsmp) {
543              uiHeaderSize = 20;              wsmp = pParentList->AddSubChunk(CHUNK_ID_WSMP, wsmpSize);
544              wsmp = pParentList->AddSubChunk(CHUNK_ID_WSMP, uiHeaderSize + SampleLoops * 16);          } else if (wsmp->GetSize() != wsmpSize) {
545                wsmp->Resize(wsmpSize);
546          }          }
547          uint8_t* pData = (uint8_t*) wsmp->LoadChunkData();          uint8_t* pData = (uint8_t*) wsmp->LoadChunkData();
548          // update headers size          // update headers size
549          memccpy(&pData[0], &uiHeaderSize, 1, 4);          store32(&pData[0], uiHeaderSize);
550          // update respective sampler options bits          // update respective sampler options bits
551          SamplerOptions = (NoSampleDepthTruncation) ? SamplerOptions | F_WSMP_NO_TRUNCATION          SamplerOptions = (NoSampleDepthTruncation) ? SamplerOptions | F_WSMP_NO_TRUNCATION
552                                                     : SamplerOptions & (~F_WSMP_NO_TRUNCATION);                                                     : SamplerOptions & (~F_WSMP_NO_TRUNCATION);
553          SamplerOptions = (NoSampleCompression) ? SamplerOptions | F_WSMP_NO_COMPRESSION          SamplerOptions = (NoSampleCompression) ? SamplerOptions | F_WSMP_NO_COMPRESSION
554                                                 : SamplerOptions & (~F_WSMP_NO_COMPRESSION);                                                 : SamplerOptions & (~F_WSMP_NO_COMPRESSION);
555            store16(&pData[4], UnityNote);
556            store16(&pData[6], FineTune);
557            store32(&pData[8], Gain);
558            store32(&pData[12], SamplerOptions);
559            store32(&pData[16], SampleLoops);
560          // update loop definitions          // update loop definitions
561          for (uint32_t i = 0; i < SampleLoops; i++) {          for (uint32_t i = 0; i < SampleLoops; i++) {
562              //FIXME: this does not handle extended loop structs correctly              //FIXME: this does not handle extended loop structs correctly
563              memccpy(&pData[uiHeaderSize + i * 16], pSampleLoops + i, 4, 4);              store32(&pData[uiHeaderSize + i * 16], pSampleLoops[i].Size);
564                store32(&pData[uiHeaderSize + i * 16 + 4], pSampleLoops[i].LoopType);
565                store32(&pData[uiHeaderSize + i * 16 + 8], pSampleLoops[i].LoopStart);
566                store32(&pData[uiHeaderSize + i * 16 + 12], pSampleLoops[i].LoopLength);
567          }          }
568      }      }
569    
570        /**
571         * Adds a new sample loop with the provided loop definition.
572         *
573         * @param pLoopDef - points to a loop definition that is to be copied
574         */
575        void Sampler::AddSampleLoop(sample_loop_t* pLoopDef) {
576            sample_loop_t* pNewLoops = new sample_loop_t[SampleLoops + 1];
577            // copy old loops array
578            for (int i = 0; i < SampleLoops; i++) {
579                pNewLoops[i] = pSampleLoops[i];
580            }
581            // add the new loop
582            pNewLoops[SampleLoops] = *pLoopDef;
583            // auto correct size field
584            pNewLoops[SampleLoops].Size = sizeof(DLS::sample_loop_t);
585            // free the old array and update the member variables
586            if (SampleLoops) delete[] pSampleLoops;
587            pSampleLoops = pNewLoops;
588            SampleLoops++;
589        }
590    
591        /**
592         * Deletes an existing sample loop.
593         *
594         * @param pLoopDef - pointer to existing loop definition
595         * @throws Exception - if given loop definition does not exist
596         */
597        void Sampler::DeleteSampleLoop(sample_loop_t* pLoopDef) {
598            sample_loop_t* pNewLoops = new sample_loop_t[SampleLoops - 1];
599            // copy old loops array (skipping given loop)
600            for (int i = 0, o = 0; i < SampleLoops; i++) {
601                if (&pSampleLoops[i] == pLoopDef) continue;
602                if (o == SampleLoops - 1)
603                    throw Exception("Could not delete Sample Loop, because it does not exist");
604                pNewLoops[o] = pSampleLoops[i];
605                o++;
606            }
607            // free the old array and update the member variables
608            if (SampleLoops) delete[] pSampleLoops;
609            pSampleLoops = pNewLoops;
610            SampleLoops--;
611        }
612    
613    
614    
615  // *************** Sample ***************  // *************** Sample ***************
# Line 494  namespace DLS { Line 643  namespace DLS {
643              AverageBytesPerSecond  = pCkFormat->ReadUint32();              AverageBytesPerSecond  = pCkFormat->ReadUint32();
644              BlockAlign             = pCkFormat->ReadUint16();              BlockAlign             = pCkFormat->ReadUint16();
645              // PCM format specific              // PCM format specific
646              if (FormatTag == WAVE_FORMAT_PCM) {              if (FormatTag == DLS_WAVE_FORMAT_PCM) {
647                  BitDepth     = pCkFormat->ReadUint16();                  BitDepth     = pCkFormat->ReadUint16();
648                  FrameSize    = (FormatTag == WAVE_FORMAT_PCM) ? (BitDepth / 8) * Channels                  FrameSize    = (BitDepth / 8) * Channels;
                                                             : 0;  
649              } else { // unsupported sample data format              } else { // unsupported sample data format
650                  BitDepth     = 0;                  BitDepth     = 0;
651                  FrameSize    = 0;                  FrameSize    = 0;
652              }              }
653          } else { // 'fmt' chunk missing          } else { // 'fmt' chunk missing
654              FormatTag              = WAVE_FORMAT_PCM;              FormatTag              = DLS_WAVE_FORMAT_PCM;
655              BitDepth               = 16;              BitDepth               = 16;
656              Channels               = 1;              Channels               = 1;
657              SamplesPerSecond       = 44100;              SamplesPerSecond       = 44100;
# Line 511  namespace DLS { Line 659  namespace DLS {
659              FrameSize              = (BitDepth / 8) * Channels;              FrameSize              = (BitDepth / 8) * Channels;
660              BlockAlign             = FrameSize;              BlockAlign             = FrameSize;
661          }          }
662          SamplesTotal = (pCkData) ? (FormatTag == WAVE_FORMAT_PCM) ? pCkData->GetSize() / FrameSize          SamplesTotal = (pCkData) ? (FormatTag == DLS_WAVE_FORMAT_PCM) ? pCkData->GetSize() / FrameSize
663                                                                    : 0                                                                        : 0
664                                   : 0;                                   : 0;
665      }      }
666    
# Line 572  namespace DLS { Line 720  namespace DLS {
720       * the RIFF chunk which encapsulates the sample's wave data. The       * the RIFF chunk which encapsulates the sample's wave data. The
721       * returned value is dependant to the current FrameSize value.       * returned value is dependant to the current FrameSize value.
722       *       *
723       * @returns number of sample points or 0 if FormatTag != WAVE_FORMAT_PCM       * @returns number of sample points or 0 if FormatTag != DLS_WAVE_FORMAT_PCM
724       * @see FrameSize, FormatTag       * @see FrameSize, FormatTag
725       */       */
726      unsigned long Sample::GetSize() {      unsigned long Sample::GetSize() {
727          if (FormatTag != WAVE_FORMAT_PCM) return 0;          if (FormatTag != DLS_WAVE_FORMAT_PCM) return 0;
728          return (pCkData) ? pCkData->GetSize() / FrameSize : 0;          return (pCkData) ? pCkData->GetSize() / FrameSize : 0;
729      }      }
730    
# Line 598  namespace DLS { Line 746  namespace DLS {
746       * calling File::Save() as this might exceed the current sample's       * calling File::Save() as this might exceed the current sample's
747       * boundary!       * boundary!
748       *       *
749       * Also note: only WAVE_FORMAT_PCM is currently supported, that is       * Also note: only DLS_WAVE_FORMAT_PCM is currently supported, that is
750       * FormatTag must be WAVE_FORMAT_PCM. Trying to resize samples with       * FormatTag must be DLS_WAVE_FORMAT_PCM. Trying to resize samples with
751       * other formats will fail!       * other formats will fail!
752       *       *
753       * @param iNewSize - new sample wave data size in sample points (must be       * @param iNewSize - new sample wave data size in sample points (must be
754       *                   greater than zero)       *                   greater than zero)
755       * @throws Excecption if FormatTag != WAVE_FORMAT_PCM       * @throws Excecption if FormatTag != DLS_WAVE_FORMAT_PCM
756       * @throws Exception if \a iNewSize is less than 1       * @throws Exception if \a iNewSize is less than 1
757       * @see File::Save(), FrameSize, FormatTag       * @see File::Save(), FrameSize, FormatTag
758       */       */
759      void Sample::Resize(int iNewSize) {      void Sample::Resize(int iNewSize) {
760          if (FormatTag != WAVE_FORMAT_PCM) throw Exception("Sample's format is not WAVE_FORMAT_PCM");          if (FormatTag != DLS_WAVE_FORMAT_PCM) throw Exception("Sample's format is not DLS_WAVE_FORMAT_PCM");
761          if (iNewSize < 1) throw Exception("Sample size must be at least one sample point");          if (iNewSize < 1) throw Exception("Sample size must be at least one sample point");
762          const int iSizeInBytes = iNewSize * FrameSize;          const int iSizeInBytes = iNewSize * FrameSize;
763          pCkData = pWaveList->GetSubChunk(CHUNK_ID_DATA);          pCkData = pWaveList->GetSubChunk(CHUNK_ID_DATA);
# Line 622  namespace DLS { Line 770  namespace DLS {
770       * bytes). Use this method and <i>Read()</i> if you don't want to load       * bytes). Use this method and <i>Read()</i> if you don't want to load
771       * the sample into RAM, thus for disk streaming.       * the sample into RAM, thus for disk streaming.
772       *       *
773       * Also note: only WAVE_FORMAT_PCM is currently supported, that is       * Also note: only DLS_WAVE_FORMAT_PCM is currently supported, that is
774       * FormatTag must be WAVE_FORMAT_PCM. Trying to reposition the sample       * FormatTag must be DLS_WAVE_FORMAT_PCM. Trying to reposition the sample
775       * with other formats will fail!       * with other formats will fail!
776       *       *
777       * @param SampleCount  number of sample points       * @param SampleCount  number of sample points
778       * @param Whence       to which relation \a SampleCount refers to       * @param Whence       to which relation \a SampleCount refers to
779       * @returns new position within the sample, 0 if       * @returns new position within the sample, 0 if
780       *          FormatTag != WAVE_FORMAT_PCM       *          FormatTag != DLS_WAVE_FORMAT_PCM
781       * @throws Exception if no data RIFF chunk was created for the sample yet       * @throws Exception if no data RIFF chunk was created for the sample yet
782       * @see FrameSize, FormatTag       * @see FrameSize, FormatTag
783       */       */
784      unsigned long Sample::SetPos(unsigned long SampleCount, RIFF::stream_whence_t Whence) {      unsigned long Sample::SetPos(unsigned long SampleCount, RIFF::stream_whence_t Whence) {
785          if (FormatTag != WAVE_FORMAT_PCM) return 0; // failed: wave data not PCM format          if (FormatTag != DLS_WAVE_FORMAT_PCM) return 0; // failed: wave data not PCM format
786          if (!pCkData) throw Exception("No data chunk created for sample yet, call Sample::Resize() to create one");          if (!pCkData) throw Exception("No data chunk created for sample yet, call Sample::Resize() to create one");
787          unsigned long orderedBytes = SampleCount * FrameSize;          unsigned long orderedBytes = SampleCount * FrameSize;
788          unsigned long result = pCkData->SetPos(orderedBytes, Whence);          unsigned long result = pCkData->SetPos(orderedBytes, Whence);
# Line 652  namespace DLS { Line 800  namespace DLS {
800       * @param SampleCount  number of sample points to read       * @param SampleCount  number of sample points to read
801       */       */
802      unsigned long Sample::Read(void* pBuffer, unsigned long SampleCount) {      unsigned long Sample::Read(void* pBuffer, unsigned long SampleCount) {
803          if (FormatTag != WAVE_FORMAT_PCM) return 0; // failed: wave data not PCM format          if (FormatTag != DLS_WAVE_FORMAT_PCM) return 0; // failed: wave data not PCM format
804          return pCkData->Read(pBuffer, SampleCount, FrameSize); // FIXME: channel inversion due to endian correction?          return pCkData->Read(pBuffer, SampleCount, FrameSize); // FIXME: channel inversion due to endian correction?
805      }      }
806    
# Line 672  namespace DLS { Line 820  namespace DLS {
820       * @see LoadSampleData()       * @see LoadSampleData()
821       */       */
822      unsigned long Sample::Write(void* pBuffer, unsigned long SampleCount) {      unsigned long Sample::Write(void* pBuffer, unsigned long SampleCount) {
823          if (FormatTag != WAVE_FORMAT_PCM) return 0; // failed: wave data not PCM format          if (FormatTag != DLS_WAVE_FORMAT_PCM) return 0; // failed: wave data not PCM format
824          if (GetSize() < SampleCount) throw Exception("Could not write sample data, current sample size to small");          if (GetSize() < SampleCount) throw Exception("Could not write sample data, current sample size to small");
825          return pCkData->Write(pBuffer, SampleCount, FrameSize); // FIXME: channel inversion due to endian correction?          return pCkData->Write(pBuffer, SampleCount, FrameSize); // FIXME: channel inversion due to endian correction?
826      }      }
# Line 681  namespace DLS { Line 829  namespace DLS {
829       * Apply sample and its settings to the respective RIFF chunks. You have       * Apply sample and its settings to the respective RIFF chunks. You have
830       * to call File::Save() to make changes persistent.       * to call File::Save() to make changes persistent.
831       *       *
832       * @throws Exception if FormatTag != WAVE_FORMAT_PCM or no sample data       * @throws Exception if FormatTag != DLS_WAVE_FORMAT_PCM or no sample data
833       *                   was provided yet       *                   was provided yet
834       */       */
835      void Sample::UpdateChunks() {      void Sample::UpdateChunks() {
836          if (FormatTag != WAVE_FORMAT_PCM)          if (FormatTag != DLS_WAVE_FORMAT_PCM)
837              throw Exception("Could not save sample, only PCM format is supported");              throw Exception("Could not save sample, only PCM format is supported");
838          // we refuse to do anything if not sample wave form was provided yet          // we refuse to do anything if not sample wave form was provided yet
839          if (!pCkData)          if (!pCkData)
# Line 697  namespace DLS { Line 845  namespace DLS {
845          if (!pCkFormat) pCkFormat = pWaveList->AddSubChunk(CHUNK_ID_FMT, 16); // assumes PCM format          if (!pCkFormat) pCkFormat = pWaveList->AddSubChunk(CHUNK_ID_FMT, 16); // assumes PCM format
846          uint8_t* pData = (uint8_t*) pCkFormat->LoadChunkData();          uint8_t* pData = (uint8_t*) pCkFormat->LoadChunkData();
847          // update 'fmt' chunk          // update 'fmt' chunk
848          memccpy(&pData[0], &FormatTag, 1, 2);          store16(&pData[0], FormatTag);
849          memccpy(&pData[2], &Channels,  1, 2);          store16(&pData[2], Channels);
850          memccpy(&pData[4], &SamplesPerSecond, 1, 4);          store32(&pData[4], SamplesPerSecond);
851          memccpy(&pData[8], &AverageBytesPerSecond, 1, 4);          store32(&pData[8], AverageBytesPerSecond);
852          memccpy(&pData[12], &BlockAlign, 1, 2);          store16(&pData[12], BlockAlign);
853          memccpy(&pData[14], &BitDepth, 1, 2); // assuming PCM format          store16(&pData[14], BitDepth); // assuming PCM format
854      }      }
855    
856    
# Line 786  namespace DLS { Line 934  namespace DLS {
934      }      }
935    
936      /**      /**
937         * Modifies the key range of this Region and makes sure the respective
938         * chunks are in correct order.
939         *
940         * @param Low  - lower end of key range
941         * @param High - upper end of key range
942         */
943        void Region::SetKeyRange(uint16_t Low, uint16_t High) {
944            KeyRange.low  = Low;
945            KeyRange.high = High;
946    
947            // make sure regions are already loaded
948            Instrument* pInstrument = (Instrument*) GetParent();
949            if (!pInstrument->pRegions) pInstrument->LoadRegions();
950            if (!pInstrument->pRegions) return;
951    
952            // find the r which is the first one to the right of this region
953            // at its new position
954            Region* r = NULL;
955            Region* prev_region = NULL;
956            for (
957                Instrument::RegionList::iterator iter = pInstrument->pRegions->begin();
958                iter != pInstrument->pRegions->end(); iter++
959            ) {
960                if ((*iter)->KeyRange.low > this->KeyRange.low) {
961                    r = *iter;
962                    break;
963                }
964                prev_region = *iter;
965            }
966    
967            // place this region before r if it's not already there
968            if (prev_region != this) pInstrument->MoveRegion(this, r);
969        }
970    
971        /**
972       * Apply Region settings to the respective RIFF chunks. You have to       * Apply Region settings to the respective RIFF chunks. You have to
973       * call File::Save() to make changes persistent.       * call File::Save() to make changes persistent.
974       *       *
# Line 794  namespace DLS { Line 977  namespace DLS {
977      void Region::UpdateChunks() {      void Region::UpdateChunks() {
978          // make sure 'rgnh' chunk exists          // make sure 'rgnh' chunk exists
979          RIFF::Chunk* rgnh = pCkRegion->GetSubChunk(CHUNK_ID_RGNH);          RIFF::Chunk* rgnh = pCkRegion->GetSubChunk(CHUNK_ID_RGNH);
980          if (!rgnh) rgnh = pCkRegion->AddSubChunk(CHUNK_ID_RGNH, 14);          if (!rgnh) rgnh = pCkRegion->AddSubChunk(CHUNK_ID_RGNH, Layer ? 14 : 12);
981          uint8_t* pData = (uint8_t*) rgnh->LoadChunkData();          uint8_t* pData = (uint8_t*) rgnh->LoadChunkData();
982          FormatOptionFlags = (SelfNonExclusive)          FormatOptionFlags = (SelfNonExclusive)
983                                  ? FormatOptionFlags | F_RGN_OPTION_SELFNONEXCLUSIVE                                  ? FormatOptionFlags | F_RGN_OPTION_SELFNONEXCLUSIVE
984                                  : FormatOptionFlags & (~F_RGN_OPTION_SELFNONEXCLUSIVE);                                  : FormatOptionFlags & (~F_RGN_OPTION_SELFNONEXCLUSIVE);
985          // update 'rgnh' chunk          // update 'rgnh' chunk
986          memccpy(&pData[0], &KeyRange, 2, 2);          store16(&pData[0], KeyRange.low);
987          memccpy(&pData[4], &VelocityRange, 2, 2);          store16(&pData[2], KeyRange.high);
988          memccpy(&pData[8], &FormatOptionFlags, 1, 2);          store16(&pData[4], VelocityRange.low);
989          memccpy(&pData[10], &KeyGroup, 1, 2);          store16(&pData[6], VelocityRange.high);
990          memccpy(&pData[12], &Layer, 1, 2);          store16(&pData[8], FormatOptionFlags);
991            store16(&pData[10], KeyGroup);
992            if (rgnh->GetSize() >= 14) store16(&pData[12], Layer);
993    
994          // update chunks of base classes as well          // update chunks of base classes as well (but skip Resource,
995          Resource::UpdateChunks();          // as a rgn doesn't seem to have dlid and INFO chunks)
996          Articulator::UpdateChunks();          Articulator::UpdateChunks();
997          Sampler::UpdateChunks();          Sampler::UpdateChunks();
998    
# Line 834  namespace DLS { Line 1019  namespace DLS {
1019                  }                  }
1020              }              }
1021          }          }
         if (index < 0) throw Exception("Could not save Region, could not find Region's sample");  
1022          WavePoolTableIndex = index;          WavePoolTableIndex = index;
1023          // update 'wlnk' chunk          // update 'wlnk' chunk
1024          memccpy(&pData[0], &WaveLinkOptionFlags, 1, 2);          store16(&pData[0], WaveLinkOptionFlags);
1025          memccpy(&pData[2], &PhaseGroup, 1, 2);          store16(&pData[2], PhaseGroup);
1026          memccpy(&pData[4], &Channel, 1, 4);          store32(&pData[4], Channel);
1027          memccpy(&pData[8], &WavePoolTableIndex, 1, 4);          store32(&pData[8], WavePoolTableIndex);
1028      }      }
1029    
1030    
# Line 923  namespace DLS { Line 1107  namespace DLS {
1107          return pNewRegion;          return pNewRegion;
1108      }      }
1109    
1110        void Instrument::MoveRegion(Region* pSrc, Region* pDst) {
1111            RIFF::List* lrgn = pCkInstrument->GetSubList(LIST_TYPE_LRGN);
1112            lrgn->MoveSubChunk(pSrc->pCkRegion, pDst ? pDst->pCkRegion : 0);
1113    
1114            pRegions->remove(pSrc);
1115            RegionList::iterator iter = find(pRegions->begin(), pRegions->end(), pDst);
1116            pRegions->insert(iter, pSrc);
1117        }
1118    
1119      void Instrument::DeleteRegion(Region* pRegion) {      void Instrument::DeleteRegion(Region* pRegion) {
1120          if (!pRegions) return;          if (!pRegions) return;
1121          RegionList::iterator iter = find(pRegions->begin(), pRegions->end(), pRegion);          RegionList::iterator iter = find(pRegions->begin(), pRegions->end(), pRegion);
# Line 953  namespace DLS { Line 1146  namespace DLS {
1146          locale.bank       = MIDI_BANK_ENCODE(MIDIBankCoarse, MIDIBankFine);          locale.bank       = MIDI_BANK_ENCODE(MIDIBankCoarse, MIDIBankFine);
1147          locale.bank       = (IsDrum) ? locale.bank | DRUM_TYPE_MASK : locale.bank & (~DRUM_TYPE_MASK);          locale.bank       = (IsDrum) ? locale.bank | DRUM_TYPE_MASK : locale.bank & (~DRUM_TYPE_MASK);
1148          MIDIBank          = MIDI_BANK_MERGE(MIDIBankCoarse, MIDIBankFine); // just a sync, when we're at it          MIDIBank          = MIDI_BANK_MERGE(MIDIBankCoarse, MIDIBankFine); // just a sync, when we're at it
1149          memccpy(&pData[0], &Regions, 1, 4);          store32(&pData[0], Regions);
1150          memccpy(&pData[4], &locale, 2, 4);          store32(&pData[4], locale.bank);
1151            store32(&pData[8], locale.instrument);
1152          // update Region's chunks          // update Region's chunks
1153          if (!pRegions) return;          if (!pRegions) return;
1154          RegionList::iterator iter = pRegions->begin();          RegionList::iterator iter = pRegions->begin();
# Line 996  namespace DLS { Line 1190  namespace DLS {
1190       * a DLS file.       * a DLS file.
1191       */       */
1192      File::File() : Resource(NULL, pRIFF = new RIFF::File(RIFF_TYPE_DLS)) {      File::File() : Resource(NULL, pRIFF = new RIFF::File(RIFF_TYPE_DLS)) {
1193            pRIFF->SetByteOrder(RIFF::endian_little);
1194          pVersion = new version_t;          pVersion = new version_t;
1195          pVersion->major   = 0;          pVersion->major   = 0;
1196          pVersion->minor   = 0;          pVersion->minor   = 0;
# Line 1039  namespace DLS { Line 1234  namespace DLS {
1234          Instruments = colh->ReadUint32();          Instruments = colh->ReadUint32();
1235    
1236          RIFF::Chunk* ptbl = pRIFF->GetSubChunk(CHUNK_ID_PTBL);          RIFF::Chunk* ptbl = pRIFF->GetSubChunk(CHUNK_ID_PTBL);
1237          if (!ptbl) throw DLS::Exception("Mandatory <ptbl> chunk not found.");          if (!ptbl) { // pool table is missing - this is probably an ".art" file
1238          WavePoolHeaderSize = ptbl->ReadUint32();              WavePoolCount    = 0;
1239          WavePoolCount  = ptbl->ReadUint32();              pWavePoolTable   = NULL;
1240          pWavePoolTable = new uint32_t[WavePoolCount];              pWavePoolTableHi = NULL;
1241          pWavePoolTableHi = new uint32_t[WavePoolCount];              WavePoolHeaderSize = 8;
1242          ptbl->SetPos(WavePoolHeaderSize);              b64BitWavePoolOffsets = false;
1243            } else {
1244          // Check for 64 bit offsets (used in gig v3 files)              WavePoolHeaderSize = ptbl->ReadUint32();
1245          b64BitWavePoolOffsets = (ptbl->GetSize() - WavePoolHeaderSize == WavePoolCount * 8);              WavePoolCount  = ptbl->ReadUint32();
1246          if (b64BitWavePoolOffsets) {              pWavePoolTable = new uint32_t[WavePoolCount];
1247              for (int i = 0 ; i < WavePoolCount ; i++) {              pWavePoolTableHi = new uint32_t[WavePoolCount];
1248                  pWavePoolTableHi[i] = ptbl->ReadUint32();              ptbl->SetPos(WavePoolHeaderSize);
1249                  pWavePoolTable[i] = ptbl->ReadUint32();  
1250                  if (pWavePoolTable[i] & 0x80000000)              // Check for 64 bit offsets (used in gig v3 files)
1251                      throw DLS::Exception("Files larger than 2 GB not yet supported");              b64BitWavePoolOffsets = (ptbl->GetSize() - WavePoolHeaderSize == WavePoolCount * 8);
1252                if (b64BitWavePoolOffsets) {
1253                    for (int i = 0 ; i < WavePoolCount ; i++) {
1254                        pWavePoolTableHi[i] = ptbl->ReadUint32();
1255                        pWavePoolTable[i] = ptbl->ReadUint32();
1256                        if (pWavePoolTable[i] & 0x80000000)
1257                            throw DLS::Exception("Files larger than 2 GB not yet supported");
1258                    }
1259                } else { // conventional 32 bit offsets
1260                    ptbl->Read(pWavePoolTable, WavePoolCount, sizeof(uint32_t));
1261                    for (int i = 0 ; i < WavePoolCount ; i++) pWavePoolTableHi[i] = 0;
1262              }              }
         } else { // conventional 32 bit offsets  
             ptbl->Read(pWavePoolTable, WavePoolCount, sizeof(uint32_t));  
             for (int i = 0 ; i < WavePoolCount ; i++) pWavePoolTableHi[i] = 0;  
1263          }          }
1264    
1265          pSamples     = NULL;          pSamples     = NULL;
# Line 1243  namespace DLS { Line 1445  namespace DLS {
1445              RIFF::Chunk* ckVersion    = pRIFF->GetSubChunk(CHUNK_ID_VERS);              RIFF::Chunk* ckVersion    = pRIFF->GetSubChunk(CHUNK_ID_VERS);
1446              if (!ckVersion) ckVersion = pRIFF->AddSubChunk(CHUNK_ID_VERS, 8);              if (!ckVersion) ckVersion = pRIFF->AddSubChunk(CHUNK_ID_VERS, 8);
1447              uint8_t* pData = (uint8_t*) ckVersion->LoadChunkData();              uint8_t* pData = (uint8_t*) ckVersion->LoadChunkData();
1448              memccpy(pData, pVersion, 2, 4);              store16(&pData[0], pVersion->minor);
1449                store16(&pData[2], pVersion->major);
1450                store16(&pData[4], pVersion->build);
1451                store16(&pData[6], pVersion->release);
1452          }          }
1453    
1454          // update 'colh' chunk          // update 'colh' chunk
# Line 1251  namespace DLS { Line 1456  namespace DLS {
1456          RIFF::Chunk* colh = pRIFF->GetSubChunk(CHUNK_ID_COLH);          RIFF::Chunk* colh = pRIFF->GetSubChunk(CHUNK_ID_COLH);
1457          if (!colh)   colh = pRIFF->AddSubChunk(CHUNK_ID_COLH, 4);          if (!colh)   colh = pRIFF->AddSubChunk(CHUNK_ID_COLH, 4);
1458          uint8_t* pData = (uint8_t*) colh->LoadChunkData();          uint8_t* pData = (uint8_t*) colh->LoadChunkData();
1459          memccpy(pData, &Instruments, 1, 4);          store32(pData, Instruments);
1460    
1461          // update instrument's chunks          // update instrument's chunks
1462          if (pInstruments) {          if (pInstruments) {
# Line 1271  namespace DLS { Line 1476  namespace DLS {
1476          ptbl->Resize(iPtblSize);          ptbl->Resize(iPtblSize);
1477          pData = (uint8_t*) ptbl->LoadChunkData();          pData = (uint8_t*) ptbl->LoadChunkData();
1478          WavePoolCount = iSamples;          WavePoolCount = iSamples;
1479          memccpy(&pData[4], &WavePoolCount, 1, 4);          store32(&pData[4], WavePoolCount);
1480          // we actually update the sample offsets in the pool table when we Save()          // we actually update the sample offsets in the pool table when we Save()
1481          memset(&pData[WavePoolHeaderSize], 0, iPtblSize - WavePoolHeaderSize);          memset(&pData[WavePoolHeaderSize], 0, iPtblSize - WavePoolHeaderSize);
1482    
# Line 1360  namespace DLS { Line 1565  namespace DLS {
1565          unsigned long ulOriginalPos = ptbl->GetPos();          unsigned long ulOriginalPos = ptbl->GetPos();
1566          // update headers          // update headers
1567          ptbl->SetPos(0);          ptbl->SetPos(0);
1568          ptbl->WriteUint32(&WavePoolHeaderSize);          uint32_t tmp = WavePoolHeaderSize;
1569          ptbl->WriteUint32(&WavePoolCount);          ptbl->WriteUint32(&tmp);
1570            tmp = WavePoolCount;
1571            ptbl->WriteUint32(&tmp);
1572          // update offsets          // update offsets
1573          ptbl->SetPos(WavePoolHeaderSize);          ptbl->SetPos(WavePoolHeaderSize);
1574          if (b64BitWavePoolOffsets) {          if (b64BitWavePoolOffsets) {
1575              for (int i = 0 ; i < WavePoolCount ; i++) {              for (int i = 0 ; i < WavePoolCount ; i++) {
1576                  ptbl->WriteUint32(&pWavePoolTableHi[i]);                  tmp = pWavePoolTableHi[i];
1577                  ptbl->WriteUint32(&pWavePoolTable[i]);                  ptbl->WriteUint32(&tmp);
1578                    tmp = pWavePoolTable[i];
1579                    ptbl->WriteUint32(&tmp);
1580              }              }
1581          } else { // conventional 32 bit offsets          } else { // conventional 32 bit offsets
1582              for (int i = 0 ; i < WavePoolCount ; i++)              for (int i = 0 ; i < WavePoolCount ; i++) {
1583                  ptbl->WriteUint32(&pWavePoolTable[i]);                  tmp = pWavePoolTable[i];
1584                    ptbl->WriteUint32(&tmp);
1585                }
1586          }          }
1587          // restore 'ptbl' chunk's original read/write position          // restore 'ptbl' chunk's original read/write position
1588          ptbl->SetPos(ulOriginalPos);          ptbl->SetPos(ulOriginalPos);

Legend:
Removed from v.834  
changed lines
  Added in v.1416

  ViewVC Help
Powered by ViewVC