/[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 1106 by schoenebeck, Sun Mar 18 19:38:47 2007 UTC revision 1953 by schoenebeck, Thu Jul 30 08:16:02 2009 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 142  namespace DLS { Line 149  namespace DLS {
149          const int iEntrySize = 12; // 12 bytes per connection block          const int iEntrySize = 12; // 12 bytes per connection block
150          pArticulationCk->Resize(HeaderSize + Connections * iEntrySize);          pArticulationCk->Resize(HeaderSize + Connections * iEntrySize);
151          uint8_t* pData = (uint8_t*) pArticulationCk->LoadChunkData();          uint8_t* pData = (uint8_t*) pArticulationCk->LoadChunkData();
152          memcpy(&pData[0], &HeaderSize, 2);          store16(&pData[0], HeaderSize);
153          memcpy(&pData[2], &Connections, 2);          store16(&pData[2], Connections);
154          for (uint32_t i = 0; i < Connections; i++) {          for (uint32_t i = 0; i < Connections; i++) {
155              Connection::conn_block_t c = pConnections[i].ToConnBlock();              Connection::conn_block_t c = pConnections[i].ToConnBlock();
156              memcpy(&pData[HeaderSize + i * iEntrySize],     &c.source, 2);              store16(&pData[HeaderSize + i * iEntrySize],     c.source);
157              memcpy(&pData[HeaderSize + i * iEntrySize + 2], &c.control, 2);              store16(&pData[HeaderSize + i * iEntrySize + 2], c.control);
158              memcpy(&pData[HeaderSize + i * iEntrySize + 4], &c.destination, 2);              store16(&pData[HeaderSize + i * iEntrySize + 4], c.destination);
159              memcpy(&pData[HeaderSize + i * iEntrySize + 6], &c.transform, 2);              store16(&pData[HeaderSize + i * iEntrySize + 6], c.transform);
160              memcpy(&pData[HeaderSize + i * iEntrySize + 8], &c.scale, 4);              store32(&pData[HeaderSize + i * iEntrySize + 8], c.scale);
161          }          }
162      }      }
163    
# 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          UseFixedLengthStrings = false;          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 286  namespace DLS { Line 308  namespace DLS {
308       * @param lstINFO  - parent (INFO) RIFF list chunk       * @param lstINFO  - parent (INFO) RIFF list chunk
309       * @param s        - current value of info field       * @param s        - current value of info field
310       * @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.  
311       */       */
312      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) {
313            int size = 0;
314            if (pFixedStringLengths) {
315                for (int i = 0 ; pFixedStringLengths[i].length ; i++) {
316                    if (pFixedStringLengths[i].chunkId == ChunkID) {
317                        size = pFixedStringLengths[i].length;
318                        break;
319                    }
320                }
321            }
322          RIFF::Chunk* ck = lstINFO->GetSubChunk(ChunkID);          RIFF::Chunk* ck = lstINFO->GetSubChunk(ChunkID);
323          ::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
324      }      }
325    
326      /** @brief Update chunks with current info values.      /** @brief Update chunks with current info values.
# Line 336  namespace DLS { Line 365  namespace DLS {
365    
366          // save values          // save values
367    
368          // (the string size values are for gig files; they are only          SaveString(CHUNK_ID_IARL, lstINFO, ArchivalLocation, String(""));
369          // used if UseFixedLengthStrings is set to true)          SaveString(CHUNK_ID_IART, lstINFO, Artists, String(""));
370          SaveString(CHUNK_ID_INAM, lstINFO, Name, defaultName, UseFixedLengthStrings,          SaveString(CHUNK_ID_ICMS, lstINFO, Commissioned, String(""));
371                     resourceType == RIFF_TYPE_DLS ? 128 : 64);          SaveString(CHUNK_ID_ICMT, lstINFO, Comments, defaultComments);
372          SaveString(CHUNK_ID_IARL, lstINFO, ArchivalLocation, String(""), UseFixedLengthStrings, 256);          SaveString(CHUNK_ID_ICOP, lstINFO, Copyright, String(""));
373          SaveString(CHUNK_ID_ICRD, lstINFO, CreationDate, defaultCreationDate, UseFixedLengthStrings, 128);          SaveString(CHUNK_ID_ICRD, lstINFO, CreationDate, defaultCreationDate);
374          SaveString(CHUNK_ID_ICMT, lstINFO, Comments, defaultComments, UseFixedLengthStrings, 1024);          SaveString(CHUNK_ID_IENG, lstINFO, Engineer, String(""));
375          SaveString(CHUNK_ID_IPRD, lstINFO, Product, String(""), UseFixedLengthStrings, 128);          SaveString(CHUNK_ID_IGNR, lstINFO, Genre, String(""));
376          SaveString(CHUNK_ID_ICOP, lstINFO, Copyright, String(""), UseFixedLengthStrings, 128);          SaveString(CHUNK_ID_IKEY, lstINFO, Keywords, String(""));
377          SaveString(CHUNK_ID_IART, lstINFO, Artists, String(""), UseFixedLengthStrings, 128);          SaveString(CHUNK_ID_IMED, lstINFO, Medium, String(""));
378          SaveString(CHUNK_ID_IGNR, lstINFO, Genre, String(""), UseFixedLengthStrings, 128);          SaveString(CHUNK_ID_INAM, lstINFO, Name, defaultName);
379          SaveString(CHUNK_ID_IKEY, lstINFO, Keywords, String(""), UseFixedLengthStrings, 128);          SaveString(CHUNK_ID_IPRD, lstINFO, Product, String(""));
380          SaveString(CHUNK_ID_IENG, lstINFO, Engineer, String(""), UseFixedLengthStrings, 128);          SaveString(CHUNK_ID_ISBJ, lstINFO, Subject, String(""));
381          SaveString(CHUNK_ID_ITCH, lstINFO, Technician, String(""), UseFixedLengthStrings, 128);          SaveString(CHUNK_ID_ISFT, lstINFO, Software, defaultSoftware);
382          SaveString(CHUNK_ID_ISFT, lstINFO, Software, defaultSoftware, UseFixedLengthStrings,          SaveString(CHUNK_ID_ISRC, lstINFO, Source, String(""));
383                     resourceType == LIST_TYPE_INS ?          SaveString(CHUNK_ID_ISRF, lstINFO, SourceForm, String(""));
384                     (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);  
385      }      }
386    
387    
# Line 406  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 425  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 450  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 457  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
550          memcpy(&pData[0], &uiHeaderSize, 4);          store32(&pData[0], uiHeaderSize);
551          // update respective sampler options bits          // update respective sampler options bits
552          SamplerOptions = (NoSampleDepthTruncation) ? SamplerOptions | F_WSMP_NO_TRUNCATION          SamplerOptions = (NoSampleDepthTruncation) ? SamplerOptions | F_WSMP_NO_TRUNCATION
553                                                     : SamplerOptions & (~F_WSMP_NO_TRUNCATION);                                                     : SamplerOptions & (~F_WSMP_NO_TRUNCATION);
554          SamplerOptions = (NoSampleCompression) ? SamplerOptions | F_WSMP_NO_COMPRESSION          SamplerOptions = (NoSampleCompression) ? SamplerOptions | F_WSMP_NO_COMPRESSION
555                                                 : SamplerOptions & (~F_WSMP_NO_COMPRESSION);                                                 : SamplerOptions & (~F_WSMP_NO_COMPRESSION);
556          memcpy(&pData[4], &UnityNote, 2);          store16(&pData[4], UnityNote);
557          memcpy(&pData[6], &FineTune, 2);          store16(&pData[6], FineTune);
558          memcpy(&pData[8], &Gain, 4);          store32(&pData[8], Gain);
559          memcpy(&pData[12], &SamplerOptions, 4);          store32(&pData[12], SamplerOptions);
560          memcpy(&pData[16], &SampleLoops, 4);          store32(&pData[16], SampleLoops);
561          // update loop definitions          // update loop definitions
562          for (uint32_t i = 0; i < SampleLoops; i++) {          for (uint32_t i = 0; i < SampleLoops; i++) {
563              //FIXME: this does not handle extended loop structs correctly              //FIXME: this does not handle extended loop structs correctly
564              memcpy(&pData[uiHeaderSize + i * 16], pSampleLoops + i, 4 * 4);              store32(&pData[uiHeaderSize + i * 16], pSampleLoops[i].Size);
565                store32(&pData[uiHeaderSize + i * 16 + 4], pSampleLoops[i].LoopType);
566                store32(&pData[uiHeaderSize + i * 16 + 8], pSampleLoops[i].LoopStart);
567                store32(&pData[uiHeaderSize + i * 16 + 12], pSampleLoops[i].LoopLength);
568          }          }
569      }      }
570    
571        /**
572         * Adds a new sample loop with the provided loop definition.
573         *
574         * @param pLoopDef - points to a loop definition that is to be copied
575         */
576        void Sampler::AddSampleLoop(sample_loop_t* pLoopDef) {
577            sample_loop_t* pNewLoops = new sample_loop_t[SampleLoops + 1];
578            // copy old loops array
579            for (int i = 0; i < SampleLoops; i++) {
580                pNewLoops[i] = pSampleLoops[i];
581            }
582            // add the new loop
583            pNewLoops[SampleLoops] = *pLoopDef;
584            // auto correct size field
585            pNewLoops[SampleLoops].Size = sizeof(DLS::sample_loop_t);
586            // free the old array and update the member variables
587            if (SampleLoops) delete[] pSampleLoops;
588            pSampleLoops = pNewLoops;
589            SampleLoops++;
590        }
591    
592        /**
593         * Deletes an existing sample loop.
594         *
595         * @param pLoopDef - pointer to existing loop definition
596         * @throws Exception - if given loop definition does not exist
597         */
598        void Sampler::DeleteSampleLoop(sample_loop_t* pLoopDef) {
599            sample_loop_t* pNewLoops = new sample_loop_t[SampleLoops - 1];
600            // copy old loops array (skipping given loop)
601            for (int i = 0, o = 0; i < SampleLoops; i++) {
602                if (&pSampleLoops[i] == pLoopDef) continue;
603                if (o == SampleLoops - 1)
604                    throw Exception("Could not delete Sample Loop, because it does not exist");
605                pNewLoops[o] = pSampleLoops[i];
606                o++;
607            }
608            // free the old array and update the member variables
609            if (SampleLoops) delete[] pSampleLoops;
610            pSampleLoops = pNewLoops;
611            SampleLoops--;
612        }
613    
614    
615    
616  // *************** Sample ***************  // *************** Sample ***************
# Line 716  namespace DLS { Line 846  namespace DLS {
846          if (!pCkFormat) pCkFormat = pWaveList->AddSubChunk(CHUNK_ID_FMT, 16); // assumes PCM format          if (!pCkFormat) pCkFormat = pWaveList->AddSubChunk(CHUNK_ID_FMT, 16); // assumes PCM format
847          uint8_t* pData = (uint8_t*) pCkFormat->LoadChunkData();          uint8_t* pData = (uint8_t*) pCkFormat->LoadChunkData();
848          // update 'fmt' chunk          // update 'fmt' chunk
849          memcpy(&pData[0], &FormatTag, 2);          store16(&pData[0], FormatTag);
850          memcpy(&pData[2], &Channels,  2);          store16(&pData[2], Channels);
851          memcpy(&pData[4], &SamplesPerSecond, 4);          store32(&pData[4], SamplesPerSecond);
852          memcpy(&pData[8], &AverageBytesPerSecond, 4);          store32(&pData[8], AverageBytesPerSecond);
853          memcpy(&pData[12], &BlockAlign, 2);          store16(&pData[12], BlockAlign);
854          memcpy(&pData[14], &BitDepth, 2); // assuming PCM format          store16(&pData[14], BitDepth); // assuming PCM format
855      }      }
856    
857    
# Line 805  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 819  namespace DLS { Line 984  namespace DLS {
984                                  ? FormatOptionFlags | F_RGN_OPTION_SELFNONEXCLUSIVE                                  ? FormatOptionFlags | F_RGN_OPTION_SELFNONEXCLUSIVE
985                                  : FormatOptionFlags & (~F_RGN_OPTION_SELFNONEXCLUSIVE);                                  : FormatOptionFlags & (~F_RGN_OPTION_SELFNONEXCLUSIVE);
986          // update 'rgnh' chunk          // update 'rgnh' chunk
987          memcpy(&pData[0], &KeyRange, 2 * 2);          store16(&pData[0], KeyRange.low);
988          memcpy(&pData[4], &VelocityRange, 2 * 2);          store16(&pData[2], KeyRange.high);
989          memcpy(&pData[8], &FormatOptionFlags, 2);          store16(&pData[4], VelocityRange.low);
990          memcpy(&pData[10], &KeyGroup, 2);          store16(&pData[6], VelocityRange.high);
991          if (rgnh->GetSize() >= 14) memcpy(&pData[12], &Layer, 2);          store16(&pData[8], FormatOptionFlags);
992            store16(&pData[10], KeyGroup);
993            if (rgnh->GetSize() >= 14) store16(&pData[12], Layer);
994    
995          // update chunks of base classes as well (but skip Resource,          // update chunks of base classes as well (but skip Resource,
996          // as a rgn doesn't seem to have dlid and INFO chunks)          // as a rgn doesn't seem to have dlid and INFO chunks)
# Line 853  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          memcpy(&pData[0], &WaveLinkOptionFlags, 2);          store16(&pData[0], WaveLinkOptionFlags);
1026          memcpy(&pData[2], &PhaseGroup, 2);          store16(&pData[2], PhaseGroup);
1027          memcpy(&pData[4], &Channel, 4);          store32(&pData[4], Channel);
1028          memcpy(&pData[8], &WavePoolTableIndex, 4);          store32(&pData[8], WavePoolTableIndex);
1029      }      }
1030    
1031    
# Line 981  namespace DLS { Line 1147  namespace DLS {
1147          locale.bank       = MIDI_BANK_ENCODE(MIDIBankCoarse, MIDIBankFine);          locale.bank       = MIDI_BANK_ENCODE(MIDIBankCoarse, MIDIBankFine);
1148          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);
1149          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
1150          memcpy(&pData[0], &Regions, 4);          store32(&pData[0], Regions);
1151          memcpy(&pData[4], &locale, 2 * 4);          store32(&pData[4], locale.bank);
1152            store32(&pData[8], locale.instrument);
1153          // update Region's chunks          // update Region's chunks
1154          if (!pRegions) return;          if (!pRegions) return;
1155          RegionList::iterator iter = pRegions->begin();          RegionList::iterator iter = pRegions->begin();
# Line 1024  namespace DLS { Line 1191  namespace DLS {
1191       * a DLS file.       * a DLS file.
1192       */       */
1193      File::File() : Resource(NULL, pRIFF = new RIFF::File(RIFF_TYPE_DLS)) {      File::File() : Resource(NULL, pRIFF = new RIFF::File(RIFF_TYPE_DLS)) {
1194            pRIFF->SetByteOrder(RIFF::endian_little);
1195          pVersion = new version_t;          pVersion = new version_t;
1196          pVersion->major   = 0;          pVersion->major   = 0;
1197          pVersion->minor   = 0;          pVersion->minor   = 0;
# Line 1278  namespace DLS { Line 1446  namespace DLS {
1446              RIFF::Chunk* ckVersion    = pRIFF->GetSubChunk(CHUNK_ID_VERS);              RIFF::Chunk* ckVersion    = pRIFF->GetSubChunk(CHUNK_ID_VERS);
1447              if (!ckVersion) ckVersion = pRIFF->AddSubChunk(CHUNK_ID_VERS, 8);              if (!ckVersion) ckVersion = pRIFF->AddSubChunk(CHUNK_ID_VERS, 8);
1448              uint8_t* pData = (uint8_t*) ckVersion->LoadChunkData();              uint8_t* pData = (uint8_t*) ckVersion->LoadChunkData();
1449              memcpy(pData, pVersion, 2 * 4);              store16(&pData[0], pVersion->minor);
1450                store16(&pData[2], pVersion->major);
1451                store16(&pData[4], pVersion->build);
1452                store16(&pData[6], pVersion->release);
1453          }          }
1454    
1455          // update 'colh' chunk          // update 'colh' chunk
# Line 1286  namespace DLS { Line 1457  namespace DLS {
1457          RIFF::Chunk* colh = pRIFF->GetSubChunk(CHUNK_ID_COLH);          RIFF::Chunk* colh = pRIFF->GetSubChunk(CHUNK_ID_COLH);
1458          if (!colh)   colh = pRIFF->AddSubChunk(CHUNK_ID_COLH, 4);          if (!colh)   colh = pRIFF->AddSubChunk(CHUNK_ID_COLH, 4);
1459          uint8_t* pData = (uint8_t*) colh->LoadChunkData();          uint8_t* pData = (uint8_t*) colh->LoadChunkData();
1460          memcpy(pData, &Instruments, 4);          store32(pData, Instruments);
1461    
1462          // update instrument's chunks          // update instrument's chunks
1463          if (pInstruments) {          if (pInstruments) {
# Line 1306  namespace DLS { Line 1477  namespace DLS {
1477          ptbl->Resize(iPtblSize);          ptbl->Resize(iPtblSize);
1478          pData = (uint8_t*) ptbl->LoadChunkData();          pData = (uint8_t*) ptbl->LoadChunkData();
1479          WavePoolCount = iSamples;          WavePoolCount = iSamples;
1480          memcpy(&pData[4], &WavePoolCount, 4);          store32(&pData[4], WavePoolCount);
1481          // 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()
1482          memset(&pData[WavePoolHeaderSize], 0, iPtblSize - WavePoolHeaderSize);          memset(&pData[WavePoolHeaderSize], 0, iPtblSize - WavePoolHeaderSize);
1483    
# Line 1395  namespace DLS { Line 1566  namespace DLS {
1566          unsigned long ulOriginalPos = ptbl->GetPos();          unsigned long ulOriginalPos = ptbl->GetPos();
1567          // update headers          // update headers
1568          ptbl->SetPos(0);          ptbl->SetPos(0);
1569          ptbl->WriteUint32(&WavePoolHeaderSize);          uint32_t tmp = WavePoolHeaderSize;
1570          ptbl->WriteUint32(&WavePoolCount);          ptbl->WriteUint32(&tmp);
1571            tmp = WavePoolCount;
1572            ptbl->WriteUint32(&tmp);
1573          // update offsets          // update offsets
1574          ptbl->SetPos(WavePoolHeaderSize);          ptbl->SetPos(WavePoolHeaderSize);
1575          if (b64BitWavePoolOffsets) {          if (b64BitWavePoolOffsets) {
1576              for (int i = 0 ; i < WavePoolCount ; i++) {              for (int i = 0 ; i < WavePoolCount ; i++) {
1577                  ptbl->WriteUint32(&pWavePoolTableHi[i]);                  tmp = pWavePoolTableHi[i];
1578                  ptbl->WriteUint32(&pWavePoolTable[i]);                  ptbl->WriteUint32(&tmp);
1579                    tmp = pWavePoolTable[i];
1580                    ptbl->WriteUint32(&tmp);
1581              }              }
1582          } else { // conventional 32 bit offsets          } else { // conventional 32 bit offsets
1583              for (int i = 0 ; i < WavePoolCount ; i++)              for (int i = 0 ; i < WavePoolCount ; i++) {
1584                  ptbl->WriteUint32(&pWavePoolTable[i]);                  tmp = pWavePoolTable[i];
1585                    ptbl->WriteUint32(&tmp);
1586                }
1587          }          }
1588          // restore 'ptbl' chunk's original read/write position          // restore 'ptbl' chunk's original read/write position
1589          ptbl->SetPos(ulOriginalPos);          ptbl->SetPos(ulOriginalPos);

Legend:
Removed from v.1106  
changed lines
  Added in v.1953

  ViewVC Help
Powered by ViewVC