/[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 1179 by persson, Sat May 12 11:25:04 2007 UTC revision 1416 by schoenebeck, Sun Oct 14 12:06:32 2007 UTC
# 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 233  namespace DLS { Line 239  namespace DLS {
239       * @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
240       */       */
241      Info::Info(RIFF::List* list) {      Info::Info(RIFF::List* list) {
242          UseFixedLengthStrings = false;          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 262  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 286  namespace DLS { Line 307  namespace DLS {
307       * @param lstINFO  - parent (INFO) RIFF list chunk       * @param lstINFO  - parent (INFO) RIFF list chunk
308       * @param s        - current value of info field       * @param s        - current value of info field
309       * @param sDefault - default value       * @param sDefault - default value
      * @param bUseFixedLengthStrings - should a specific string size be forced in the chunk?  
      * @param size     - wanted size of the INFO chunk. This is ignored if bUseFixedLengthStrings is false.  
310       */       */
311      void Info::SaveString(uint32_t ChunkID, RIFF::List* lstINFO, const String& s, const String& sDefault, bool bUseFixedLengthStrings, int size) {      void Info::SaveString(uint32_t ChunkID, RIFF::List* lstINFO, const String& s, const String& sDefault) {
312            int size = 0;
313            if (pFixedStringLengths) {
314                for (int i = 0 ; pFixedStringLengths[i].length ; i++) {
315                    if (pFixedStringLengths[i].chunkId == ChunkID) {
316                        size = pFixedStringLengths[i].length;
317                        break;
318                    }
319                }
320            }
321          RIFF::Chunk* ck = lstINFO->GetSubChunk(ChunkID);          RIFF::Chunk* ck = lstINFO->GetSubChunk(ChunkID);
322          ::SaveString(ChunkID, ck, lstINFO, s, sDefault, bUseFixedLengthStrings, size); // function from helper.h          ::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 336  namespace DLS { Line 364  namespace DLS {
364    
365          // save values          // save values
366    
367          // (the string size values are for gig files; they are only          SaveString(CHUNK_ID_IARL, lstINFO, ArchivalLocation, String(""));
368          // used if UseFixedLengthStrings is set to true)          SaveString(CHUNK_ID_IART, lstINFO, Artists, String(""));
369          SaveString(CHUNK_ID_INAM, lstINFO, Name, defaultName, UseFixedLengthStrings,          SaveString(CHUNK_ID_ICMS, lstINFO, Commissioned, String(""));
370                     resourceType == RIFF_TYPE_DLS ? 128 : 64);          SaveString(CHUNK_ID_ICMT, lstINFO, Comments, defaultComments);
371          SaveString(CHUNK_ID_IARL, lstINFO, ArchivalLocation, String(""), UseFixedLengthStrings, 256);          SaveString(CHUNK_ID_ICOP, lstINFO, Copyright, String(""));
372          SaveString(CHUNK_ID_ICRD, lstINFO, CreationDate, defaultCreationDate, UseFixedLengthStrings, 128);          SaveString(CHUNK_ID_ICRD, lstINFO, CreationDate, defaultCreationDate);
373          SaveString(CHUNK_ID_ICMT, lstINFO, Comments, defaultComments, UseFixedLengthStrings, 1024);          SaveString(CHUNK_ID_IENG, lstINFO, Engineer, String(""));
374          SaveString(CHUNK_ID_IPRD, lstINFO, Product, String(""), UseFixedLengthStrings, 128);          SaveString(CHUNK_ID_IGNR, lstINFO, Genre, String(""));
375          SaveString(CHUNK_ID_ICOP, lstINFO, Copyright, String(""), UseFixedLengthStrings, 128);          SaveString(CHUNK_ID_IKEY, lstINFO, Keywords, String(""));
376          SaveString(CHUNK_ID_IART, lstINFO, Artists, String(""), UseFixedLengthStrings, 128);          SaveString(CHUNK_ID_IMED, lstINFO, Medium, String(""));
377          SaveString(CHUNK_ID_IGNR, lstINFO, Genre, String(""), UseFixedLengthStrings, 128);          SaveString(CHUNK_ID_INAM, lstINFO, Name, defaultName);
378          SaveString(CHUNK_ID_IKEY, lstINFO, Keywords, String(""), UseFixedLengthStrings, 128);          SaveString(CHUNK_ID_IPRD, lstINFO, Product, String(""));
379          SaveString(CHUNK_ID_IENG, lstINFO, Engineer, String(""), UseFixedLengthStrings, 128);          SaveString(CHUNK_ID_ISBJ, lstINFO, Subject, String(""));
380          SaveString(CHUNK_ID_ITCH, lstINFO, Technician, String(""), UseFixedLengthStrings, 128);          SaveString(CHUNK_ID_ISFT, lstINFO, Software, defaultSoftware);
381          SaveString(CHUNK_ID_ISFT, lstINFO, Software, defaultSoftware, UseFixedLengthStrings,          SaveString(CHUNK_ID_ISRC, lstINFO, Source, String(""));
382                     resourceType == LIST_TYPE_INS ?          SaveString(CHUNK_ID_ISRF, lstINFO, SourceForm, String(""));
383                     (Software == "" ? defaultSoftware.length()+1 : Software.length()+1) : 128);          SaveString(CHUNK_ID_ITCH, lstINFO, Technician, String(""));
         SaveString(CHUNK_ID_IMED, lstINFO, Medium, String(""), UseFixedLengthStrings, 128);  
         SaveString(CHUNK_ID_ISRC, lstINFO, Source, String(""), UseFixedLengthStrings, 128);  
         SaveString(CHUNK_ID_ISRF, lstINFO, SourceForm, String(""), UseFixedLengthStrings, 128);  
         SaveString(CHUNK_ID_ICMS, lstINFO, Commissioned, String(""), UseFixedLengthStrings, 128);  
         SaveString(CHUNK_ID_ISBJ, lstINFO, Subject, String(""), UseFixedLengthStrings, 128);  
384      }      }
385    
386    
# Line 406  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 425  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 450  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 457  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
# Line 487  namespace DLS { Line 570  namespace DLS {
570      /**      /**
571       * Adds a new sample loop with the provided loop definition.       * Adds a new sample loop with the provided loop definition.
572       *       *
573       * @param - points to a loop definition that is to be copied       * @param pLoopDef - points to a loop definition that is to be copied
574       */       */
575      void Sampler::AddSampleLoop(sample_loop_t* pLoopDef) {      void Sampler::AddSampleLoop(sample_loop_t* pLoopDef) {
576          sample_loop_t* pNewLoops = new sample_loop_t[SampleLoops + 1];          sample_loop_t* pNewLoops = new sample_loop_t[SampleLoops + 1];
# Line 851  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 901  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          store16(&pData[0], WaveLinkOptionFlags);          store16(&pData[0], WaveLinkOptionFlags);
# Line 1073  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;

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

  ViewVC Help
Powered by ViewVC