/[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 1184 by persson, Sun May 13 13:24:22 2007 UTC revision 1713 by persson, Thu Mar 6 20:42:22 2008 UTC
# Line 23  Line 23 
23    
24  #include "DLS.h"  #include "DLS.h"
25    
26    #include <algorithm>
27  #include <time.h>  #include <time.h>
28    
29    #ifdef __APPLE__
30    #include <CoreFoundation/CFUUID.h>
31    #elif defined(HAVE_UUID_UUID_H)
32    #include <uuid/uuid.h>
33    #endif
34    
35  #include "helper.h"  #include "helper.h"
36    
37  // macros to decode connection transforms  // macros to decode connection transforms
# Line 233  namespace DLS { Line 240  namespace DLS {
240       * @param list - pointer to a list chunk which contains an INFO list chunk       * @param list - pointer to a list chunk which contains an INFO list chunk
241       */       */
242      Info::Info(RIFF::List* list) {      Info::Info(RIFF::List* list) {
243          FixedStringLengths = NULL;          pFixedStringLengths = NULL;
244          pResourceListChunk = list;          pResourceListChunk = list;
245          if (list) {          if (list) {
246              RIFF::List* lstINFO = list->GetSubList(LIST_TYPE_INFO);              RIFF::List* lstINFO = list->GetSubList(LIST_TYPE_INFO);
# Line 262  namespace DLS { Line 269  namespace DLS {
269      Info::~Info() {      Info::~Info() {
270      }      }
271    
272        /**
273         * Forces specific Info fields to be of a fixed length when being saved
274         * to a file. By default the respective RIFF chunk of an Info field
275         * will have a size analogue to its actual string length. With this
276         * method however this behavior can be overridden, allowing to force an
277         * arbitrary fixed size individually for each Info field.
278         *
279         * This method is used as a workaround for the gig format, not for DLS.
280         *
281         * @param lengths - NULL terminated array of string_length_t elements
282         */
283        void Info::SetFixedStringLengths(const string_length_t* lengths) {
284            pFixedStringLengths = lengths;
285        }
286    
287      /** @brief Load given INFO field.      /** @brief Load given INFO field.
288       *       *
289       * 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 289  namespace DLS { Line 311  namespace DLS {
311       */       */
312      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) {
313          int size = 0;          int size = 0;
314          if (FixedStringLengths) {          if (pFixedStringLengths) {
315              for (int i = 0 ; FixedStringLengths[i].length ; i++) {              for (int i = 0 ; pFixedStringLengths[i].length ; i++) {
316                  if (FixedStringLengths[i].chunkId == ChunkID) {                  if (pFixedStringLengths[i].chunkId == ChunkID) {
317                      size = FixedStringLengths[i].length;                      size = pFixedStringLengths[i].length;
318                        break;
319                  }                  }
320              }              }
321          }          }
# Line 407  namespace DLS { Line 430  namespace DLS {
430       */       */
431      void Resource::UpdateChunks() {      void Resource::UpdateChunks() {
432          pInfo->UpdateChunks();          pInfo->UpdateChunks();
433          //TODO: save DLSID  
434            if (pDLSID) {
435                // make sure 'dlid' chunk exists
436                RIFF::Chunk* ckDLSID = pResourceList->GetSubChunk(CHUNK_ID_DLID);
437                if (!ckDLSID) ckDLSID = pResourceList->AddSubChunk(CHUNK_ID_DLID, 16);
438                uint8_t* pData = (uint8_t*)ckDLSID->LoadChunkData();
439                // update 'dlid' chunk
440                store32(&pData[0], pDLSID->ulData1);
441                store16(&pData[4], pDLSID->usData2);
442                store16(&pData[6], pDLSID->usData3);
443                memcpy(&pData[8], pDLSID->abData, 8);
444            }
445      }      }
446    
447        /**
448         * Generates a new DLSID for the resource.
449         */
450        void Resource::GenerateDLSID() {
451    #if defined(WIN32) || defined(__APPLE__) || defined(HAVE_UUID_GENERATE)
452    
453            if (!pDLSID) pDLSID = new dlsid_t;
454    
455    #ifdef WIN32
456    
457            UUID uuid;
458            UuidCreate(&uuid);
459            pDLSID->ulData1 = uuid.Data1;
460            pDLSID->usData2 = uuid.Data2;
461            pDLSID->usData3 = uuid.Data3;
462            memcpy(pDLSID->abData, uuid.Data4, 8);
463    
464    #elif defined(__APPLE__)
465    
466            CFUUIDRef uuidRef = CFUUIDCreate(NULL);
467            CFUUIDBytes uuid = CFUUIDGetUUIDBytes(uuidRef);
468            CFRelease(uuidRef);
469            pDLSID->ulData1 = uuid.byte0 | uuid.byte1 << 8 | uuid.byte2 << 16 | uuid.byte3 << 24;
470            pDLSID->usData2 = uuid.byte4 | uuid.byte5 << 8;
471            pDLSID->usData3 = uuid.byte6 | uuid.byte7 << 8;
472            pDLSID->abData[0] = uuid.byte8;
473            pDLSID->abData[1] = uuid.byte9;
474            pDLSID->abData[2] = uuid.byte10;
475            pDLSID->abData[3] = uuid.byte11;
476            pDLSID->abData[4] = uuid.byte12;
477            pDLSID->abData[5] = uuid.byte13;
478            pDLSID->abData[6] = uuid.byte14;
479            pDLSID->abData[7] = uuid.byte15;
480    #else
481            uuid_t uuid;
482            uuid_generate(uuid);
483            pDLSID->ulData1 = uuid[0] | uuid[1] << 8 | uuid[2] << 16 | uuid[3] << 24;
484            pDLSID->usData2 = uuid[4] | uuid[5] << 8;
485            pDLSID->usData3 = uuid[6] | uuid[7] << 8;
486            memcpy(pDLSID->abData, &uuid[8], 8);
487    #endif
488    #endif
489        }
490    
491    
492  // *************** Sampler ***************  // *************** Sampler ***************
# Line 426  namespace DLS { Line 503  namespace DLS {
503              SamplerOptions = wsmp->ReadUint32();              SamplerOptions = wsmp->ReadUint32();
504              SampleLoops    = wsmp->ReadUint32();              SampleLoops    = wsmp->ReadUint32();
505          } else { // 'wsmp' chunk missing          } else { // 'wsmp' chunk missing
506              uiHeaderSize   = 0;              uiHeaderSize   = 20;
507              UnityNote      = 64;              UnityNote      = 60;
508              FineTune       = 0; // +- 0 cents              FineTune       = 0; // +- 0 cents
509              Gain           = 0; // 0 dB              Gain           = 0; // 0 dB
510              SamplerOptions = F_WSMP_NO_COMPRESSION;              SamplerOptions = F_WSMP_NO_COMPRESSION;
# Line 451  namespace DLS { Line 528  namespace DLS {
528          if (pSampleLoops) delete[] pSampleLoops;          if (pSampleLoops) delete[] pSampleLoops;
529      }      }
530    
531        void Sampler::SetGain(int32_t gain) {
532            Gain = gain;
533        }
534    
535      /**      /**
536       * Apply all sample player options to the respective RIFF chunk. You       * Apply all sample player options to the respective RIFF chunk. You
537       * have to call File::Save() to make changes persistent.       * have to call File::Save() to make changes persistent.
# Line 458  namespace DLS { Line 539  namespace DLS {
539      void Sampler::UpdateChunks() {      void Sampler::UpdateChunks() {
540          // make sure 'wsmp' chunk exists          // make sure 'wsmp' chunk exists
541          RIFF::Chunk* wsmp = pParentList->GetSubChunk(CHUNK_ID_WSMP);          RIFF::Chunk* wsmp = pParentList->GetSubChunk(CHUNK_ID_WSMP);
542            int wsmpSize = uiHeaderSize + SampleLoops * 16;
543          if (!wsmp) {          if (!wsmp) {
544              uiHeaderSize = 20;              wsmp = pParentList->AddSubChunk(CHUNK_ID_WSMP, wsmpSize);
545              wsmp = pParentList->AddSubChunk(CHUNK_ID_WSMP, uiHeaderSize + SampleLoops * 16);          } else if (wsmp->GetSize() != wsmpSize) {
546                wsmp->Resize(wsmpSize);
547          }          }
548          uint8_t* pData = (uint8_t*) wsmp->LoadChunkData();          uint8_t* pData = (uint8_t*) wsmp->LoadChunkData();
549          // update headers size          // update headers size
# Line 488  namespace DLS { Line 571  namespace DLS {
571      /**      /**
572       * Adds a new sample loop with the provided loop definition.       * Adds a new sample loop with the provided loop definition.
573       *       *
574       * @param - points to a loop definition that is to be copied       * @param pLoopDef - points to a loop definition that is to be copied
575       */       */
576      void Sampler::AddSampleLoop(sample_loop_t* pLoopDef) {      void Sampler::AddSampleLoop(sample_loop_t* pLoopDef) {
577          sample_loop_t* pNewLoops = new sample_loop_t[SampleLoops + 1];          sample_loop_t* pNewLoops = new sample_loop_t[SampleLoops + 1];
# Line 852  namespace DLS { Line 935  namespace DLS {
935      }      }
936    
937      /**      /**
938         * Modifies the key range of this Region and makes sure the respective
939         * chunks are in correct order.
940         *
941         * @param Low  - lower end of key range
942         * @param High - upper end of key range
943         */
944        void Region::SetKeyRange(uint16_t Low, uint16_t High) {
945            KeyRange.low  = Low;
946            KeyRange.high = High;
947    
948            // make sure regions are already loaded
949            Instrument* pInstrument = (Instrument*) GetParent();
950            if (!pInstrument->pRegions) pInstrument->LoadRegions();
951            if (!pInstrument->pRegions) return;
952    
953            // find the r which is the first one to the right of this region
954            // at its new position
955            Region* r = NULL;
956            Region* prev_region = NULL;
957            for (
958                Instrument::RegionList::iterator iter = pInstrument->pRegions->begin();
959                iter != pInstrument->pRegions->end(); iter++
960            ) {
961                if ((*iter)->KeyRange.low > this->KeyRange.low) {
962                    r = *iter;
963                    break;
964                }
965                prev_region = *iter;
966            }
967    
968            // place this region before r if it's not already there
969            if (prev_region != this) pInstrument->MoveRegion(this, r);
970        }
971    
972        /**
973       * Apply Region settings to the respective RIFF chunks. You have to       * Apply Region settings to the respective RIFF chunks. You have to
974       * call File::Save() to make changes persistent.       * call File::Save() to make changes persistent.
975       *       *
# Line 902  namespace DLS { Line 1020  namespace DLS {
1020                  }                  }
1021              }              }
1022          }          }
         if (index < 0) throw Exception("Could not save Region, could not find Region's sample");  
1023          WavePoolTableIndex = index;          WavePoolTableIndex = index;
1024          // update 'wlnk' chunk          // update 'wlnk' chunk
1025          store16(&pData[0], WaveLinkOptionFlags);          store16(&pData[0], WaveLinkOptionFlags);

Legend:
Removed from v.1184  
changed lines
  Added in v.1713

  ViewVC Help
Powered by ViewVC