/[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 2310 by persson, Sat Feb 11 11:08:01 2012 UTC
# Line 2  Line 2 
2   *                                                                         *   *                                                                         *
3   *   libgig - C++ cross-platform Gigasampler format file access library    *   *   libgig - C++ cross-platform Gigasampler format file access library    *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003-2007 by Christian Schoenebeck                      *   *   Copyright (C) 2003-2009 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 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 517  namespace DLS { Line 600  namespace DLS {
600          // copy old loops array (skipping given loop)          // copy old loops array (skipping given loop)
601          for (int i = 0, o = 0; i < SampleLoops; i++) {          for (int i = 0, o = 0; i < SampleLoops; i++) {
602              if (&pSampleLoops[i] == pLoopDef) continue;              if (&pSampleLoops[i] == pLoopDef) continue;
603              if (o == SampleLoops - 1)              if (o == SampleLoops - 1) {
604                    delete[] pNewLoops;
605                  throw Exception("Could not delete Sample Loop, because it does not exist");                  throw Exception("Could not delete Sample Loop, because it does not exist");
606                }
607              pNewLoops[o] = pSampleLoops[i];              pNewLoops[o] = pSampleLoops[i];
608              o++;              o++;
609          }          }
# Line 852  namespace DLS { Line 937  namespace DLS {
937      }      }
938    
939      /**      /**
940         * Modifies the key range of this Region and makes sure the respective
941         * chunks are in correct order.
942         *
943         * @param Low  - lower end of key range
944         * @param High - upper end of key range
945         */
946        void Region::SetKeyRange(uint16_t Low, uint16_t High) {
947            KeyRange.low  = Low;
948            KeyRange.high = High;
949    
950            // make sure regions are already loaded
951            Instrument* pInstrument = (Instrument*) GetParent();
952            if (!pInstrument->pRegions) pInstrument->LoadRegions();
953            if (!pInstrument->pRegions) return;
954    
955            // find the r which is the first one to the right of this region
956            // at its new position
957            Region* r = NULL;
958            Region* prev_region = NULL;
959            for (
960                Instrument::RegionList::iterator iter = pInstrument->pRegions->begin();
961                iter != pInstrument->pRegions->end(); iter++
962            ) {
963                if ((*iter)->KeyRange.low > this->KeyRange.low) {
964                    r = *iter;
965                    break;
966                }
967                prev_region = *iter;
968            }
969    
970            // place this region before r if it's not already there
971            if (prev_region != this) pInstrument->MoveRegion(this, r);
972        }
973    
974        /**
975       * Apply Region settings to the respective RIFF chunks. You have to       * Apply Region settings to the respective RIFF chunks. You have to
976       * call File::Save() to make changes persistent.       * call File::Save() to make changes persistent.
977       *       *
# Line 902  namespace DLS { Line 1022  namespace DLS {
1022                  }                  }
1023              }              }
1024          }          }
         if (index < 0) throw Exception("Could not save Region, could not find Region's sample");  
1025          WavePoolTableIndex = index;          WavePoolTableIndex = index;
1026          // update 'wlnk' chunk          // update 'wlnk' chunk
1027          store16(&pData[0], WaveLinkOptionFlags);          store16(&pData[0], WaveLinkOptionFlags);
# Line 1313  namespace DLS { Line 1432  namespace DLS {
1432          delete pInstrument;          delete pInstrument;
1433      }      }
1434    
1435        /** @brief File name of this DLS file.
1436         *
1437         * This method returns the file name as it was provided when loading
1438         * the respective DLS file. However in case the File object associates
1439         * an empty, that is new DLS file, which was not yet saved to disk,
1440         * this method will return an empty string.
1441         */
1442        String File::GetFileName() {
1443            return pRIFF->GetFileName();
1444        }
1445    
1446      /**      /**
1447       * Apply all the DLS file's current instruments, samples and settings to       * Apply all the DLS file's current instruments, samples and settings to
1448       * the respective RIFF chunks. You have to call Save() to make changes       * the respective RIFF chunks. You have to call Save() to make changes

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

  ViewVC Help
Powered by ViewVC