/[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 902 by persson, Sat Jul 22 14:22:01 2006 UTC revision 928 by persson, Tue Oct 24 19:32:47 2006 UTC
# Line 45  Line 45 
45  #define CONN_TRANSFORM_INVERT_SRC_ENCODE(x)             ((x) ? 0x8000 : 0)  #define CONN_TRANSFORM_INVERT_SRC_ENCODE(x)             ((x) ? 0x8000 : 0)
46  #define CONN_TRANSFORM_INVERT_CTL_ENCODE(x)             ((x) ? 0x0200 : 0)  #define CONN_TRANSFORM_INVERT_CTL_ENCODE(x)             ((x) ? 0x0200 : 0)
47    
48  #define DRUM_TYPE_MASK                  0x00000001  #define DRUM_TYPE_MASK                  0x80000000
49    
50  #define F_RGN_OPTION_SELFNONEXCLUSIVE   0x0001  #define F_RGN_OPTION_SELFNONEXCLUSIVE   0x0001
51    
# Line 142  namespace DLS { Line 142  namespace DLS {
142          const int iEntrySize = 12; // 12 bytes per connection block          const int iEntrySize = 12; // 12 bytes per connection block
143          pArticulationCk->Resize(HeaderSize + Connections * iEntrySize);          pArticulationCk->Resize(HeaderSize + Connections * iEntrySize);
144          uint8_t* pData = (uint8_t*) pArticulationCk->LoadChunkData();          uint8_t* pData = (uint8_t*) pArticulationCk->LoadChunkData();
145          memccpy(&pData[0], &HeaderSize, 1, 2);          memcpy(&pData[0], &HeaderSize, 2);
146          memccpy(&pData[2], &Connections, 1, 2);          memcpy(&pData[2], &Connections, 2);
147          for (uint32_t i = 0; i < Connections; i++) {          for (uint32_t i = 0; i < Connections; i++) {
148              Connection::conn_block_t c = pConnections[i].ToConnBlock();              Connection::conn_block_t c = pConnections[i].ToConnBlock();
149              memccpy(&pData[HeaderSize + i * iEntrySize],     &c.source, 1, 2);              memcpy(&pData[HeaderSize + i * iEntrySize],     &c.source, 2);
150              memccpy(&pData[HeaderSize + i * iEntrySize + 2], &c.control, 1, 2);              memcpy(&pData[HeaderSize + i * iEntrySize + 2], &c.control, 2);
151              memccpy(&pData[HeaderSize + i * iEntrySize + 4], &c.destination, 1, 2);              memcpy(&pData[HeaderSize + i * iEntrySize + 4], &c.destination, 2);
152              memccpy(&pData[HeaderSize + i * iEntrySize + 6], &c.transform, 1, 2);              memcpy(&pData[HeaderSize + i * iEntrySize + 6], &c.transform, 2);
153              memccpy(&pData[HeaderSize + i * iEntrySize + 8], &c.scale, 1, 4);              memcpy(&pData[HeaderSize + i * iEntrySize + 8], &c.scale, 4);
154          }          }
155      }      }
156    
# Line 233  namespace DLS { Line 233  namespace DLS {
233       * @param list - pointer to a list chunk which contains a INFO list chunk       * @param list - pointer to a list chunk which contains a INFO list chunk
234       */       */
235      Info::Info(RIFF::List* list) {      Info::Info(RIFF::List* list) {
236            UseFixedLengthStrings = false;
237          pResourceListChunk = list;          pResourceListChunk = list;
238          if (list) {          if (list) {
239              RIFF::List* lstINFO = list->GetSubList(LIST_TYPE_INFO);              RIFF::List* lstINFO = list->GetSubList(LIST_TYPE_INFO);
# Line 253  namespace DLS { Line 254  namespace DLS {
254                  LoadString(CHUNK_ID_ISRC, lstINFO, Source);                  LoadString(CHUNK_ID_ISRC, lstINFO, Source);
255                  LoadString(CHUNK_ID_ISRF, lstINFO, SourceForm);                  LoadString(CHUNK_ID_ISRF, lstINFO, SourceForm);
256                  LoadString(CHUNK_ID_ICMS, lstINFO, Commissioned);                  LoadString(CHUNK_ID_ICMS, lstINFO, Commissioned);
257                    LoadString(CHUNK_ID_ISBJ, lstINFO, Subject);
258              }              }
259          }          }
260      }      }
# Line 292  namespace DLS { Line 294  namespace DLS {
294       * @param lstINFO  - parent (INFO) RIFF list chunk       * @param lstINFO  - parent (INFO) RIFF list chunk
295       * @param s        - current value of info field       * @param s        - current value of info field
296       * @param sDefault - default value       * @param sDefault - default value
297         * @param size     - wanted size of the INFO chunk. This is ignored if UseFixedLengthStrings is false.
298       */       */
299      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, int size) {
300          RIFF::Chunk* ck = lstINFO->GetSubChunk(ChunkID);          RIFF::Chunk* ck = lstINFO->GetSubChunk(ChunkID);
301          if (ck) { // if chunk exists already, use 's' as value          if (ck) { // if chunk exists already, use 's' as value
302              ck->Resize(s.size() + 1);              if (!UseFixedLengthStrings) size = s.size() + 1;
303                ck->Resize(size);
304              char* pData = (char*) ck->LoadChunkData();              char* pData = (char*) ck->LoadChunkData();
305              memcpy(pData, s.c_str(), s.size() + 1);              strncpy(pData, s.c_str(), size);
306          } else if (s != "" || sDefault != "") { // create chunk          } else if (s != "" || sDefault != "") { // create chunk
307              const String& sToSave = (s != "") ? s : sDefault;              const String& sToSave = (s != "") ? s : sDefault;
308              ck = lstINFO->AddSubChunk(ChunkID, sToSave.size() + 1);              if (!UseFixedLengthStrings) size = sToSave.size() + 1;
309                ck = lstINFO->AddSubChunk(ChunkID, size);
310              char* pData = (char*) ck->LoadChunkData();              char* pData = (char*) ck->LoadChunkData();
311              memcpy(pData, sToSave.c_str(), sToSave.size() + 1);              strncpy(pData, sToSave.c_str(), size);
312          }          }
313      }      }
314    
# Line 317  namespace DLS { Line 322  namespace DLS {
322    
323          // make sure INFO list chunk exists          // make sure INFO list chunk exists
324          RIFF::List* lstINFO   = pResourceListChunk->GetSubList(LIST_TYPE_INFO);          RIFF::List* lstINFO   = pResourceListChunk->GetSubList(LIST_TYPE_INFO);
         if (!lstINFO) lstINFO = pResourceListChunk->AddSubList(LIST_TYPE_INFO);  
325    
326          // assemble default values in case the respective chunk is missing yet          String defaultName = "";
327          String defaultName = "NONAME";          String defaultCreationDate = "";
328          // get current date          String defaultSoftware = "";
329          time_t now = time(NULL);          String defaultComments = "";
330          tm* pNowBroken = localtime(&now);  
331          String defaultCreationDate = ToString(1900 + pNowBroken->tm_year) + "-" +          uint32_t resourceType = pResourceListChunk->GetListType();
332                                       ToString(pNowBroken->tm_mon + 1)  + "-" +  
333                                       ToString(pNowBroken->tm_mday);          if (!lstINFO) {
334          String defaultSoftware = libraryName() + " " + libraryVersion();              lstINFO = pResourceListChunk->AddSubList(LIST_TYPE_INFO);
335          String defaultComments = "Created with " + libraryName() + " " + libraryVersion();  
336                // assemble default values
337                defaultName = "NONAME";
338    
339                if (resourceType == RIFF_TYPE_DLS) {
340                    // get current date
341                    time_t now = time(NULL);
342                    tm* pNowBroken = localtime(&now);
343                    char buf[11];
344                    strftime(buf, 11, "%F", pNowBroken);
345                    defaultCreationDate = buf;
346    
347                    defaultComments = "Created with " + libraryName() + " " + libraryVersion();
348                }
349                if (resourceType == RIFF_TYPE_DLS || resourceType == LIST_TYPE_INS)
350                {
351                    defaultSoftware = libraryName() + " " + libraryVersion();
352                }
353            }
354    
355          // save values          // save values
356          SaveString(CHUNK_ID_INAM, lstINFO, Name, defaultName);  
357          SaveString(CHUNK_ID_IARL, lstINFO, ArchivalLocation, String(""));          // (the string size values are for gig files; they are only
358          SaveString(CHUNK_ID_ICRD, lstINFO, CreationDate, defaultCreationDate);          // used if UseFixedLengthStrings is set to true)
359          SaveString(CHUNK_ID_ICMT, lstINFO, Comments, defaultComments);          SaveString(CHUNK_ID_INAM, lstINFO, Name, defaultName,
360          SaveString(CHUNK_ID_IPRD, lstINFO, Product, String(""));                     resourceType == RIFF_TYPE_DLS ? 128 : 64);
361          SaveString(CHUNK_ID_ICOP, lstINFO, Copyright, String(""));          SaveString(CHUNK_ID_IARL, lstINFO, ArchivalLocation, String(""), 256);
362          SaveString(CHUNK_ID_IART, lstINFO, Artists, String(""));          SaveString(CHUNK_ID_ICRD, lstINFO, CreationDate, defaultCreationDate, 128);
363          SaveString(CHUNK_ID_IGNR, lstINFO, Genre, String(""));          SaveString(CHUNK_ID_ICMT, lstINFO, Comments, defaultComments, 1024);
364          SaveString(CHUNK_ID_IKEY, lstINFO, Keywords, String(""));          SaveString(CHUNK_ID_IPRD, lstINFO, Product, String(""), 128);
365          SaveString(CHUNK_ID_IENG, lstINFO, Engineer, String(""));          SaveString(CHUNK_ID_ICOP, lstINFO, Copyright, String(""), 128);
366          SaveString(CHUNK_ID_ITCH, lstINFO, Technician, String(""));          SaveString(CHUNK_ID_IART, lstINFO, Artists, String(""), 128);
367          SaveString(CHUNK_ID_ISFT, lstINFO, Software, defaultSoftware);          SaveString(CHUNK_ID_IGNR, lstINFO, Genre, String(""), 128);
368          SaveString(CHUNK_ID_IMED, lstINFO, Medium, String(""));          SaveString(CHUNK_ID_IKEY, lstINFO, Keywords, String(""), 128);
369          SaveString(CHUNK_ID_ISRC, lstINFO, Source, String(""));          SaveString(CHUNK_ID_IENG, lstINFO, Engineer, String(""), 128);
370          SaveString(CHUNK_ID_ISRF, lstINFO, SourceForm, String(""));          SaveString(CHUNK_ID_ITCH, lstINFO, Technician, String(""), 128);
371          SaveString(CHUNK_ID_ICMS, lstINFO, Commissioned, String(""));          SaveString(CHUNK_ID_ISFT, lstINFO, Software, defaultSoftware,
372                       resourceType == LIST_TYPE_INS ?
373                       (Software == "" ? defaultSoftware.length() : Software.length()) : 128);
374            SaveString(CHUNK_ID_IMED, lstINFO, Medium, String(""), 128);
375            SaveString(CHUNK_ID_ISRC, lstINFO, Source, String(""), 128);
376            SaveString(CHUNK_ID_ISRF, lstINFO, SourceForm, String(""), 128);
377            SaveString(CHUNK_ID_ICMS, lstINFO, Commissioned, String(""), 128);
378            SaveString(CHUNK_ID_ISBJ, lstINFO, Subject, String(""), 128);
379      }      }
380    
381    
# Line 452  namespace DLS { Line 481  namespace DLS {
481          }          }
482          uint8_t* pData = (uint8_t*) wsmp->LoadChunkData();          uint8_t* pData = (uint8_t*) wsmp->LoadChunkData();
483          // update headers size          // update headers size
484          memccpy(&pData[0], &uiHeaderSize, 1, 4);          memcpy(&pData[0], &uiHeaderSize, 4);
485          // update respective sampler options bits          // update respective sampler options bits
486          SamplerOptions = (NoSampleDepthTruncation) ? SamplerOptions | F_WSMP_NO_TRUNCATION          SamplerOptions = (NoSampleDepthTruncation) ? SamplerOptions | F_WSMP_NO_TRUNCATION
487                                                     : SamplerOptions & (~F_WSMP_NO_TRUNCATION);                                                     : SamplerOptions & (~F_WSMP_NO_TRUNCATION);
488          SamplerOptions = (NoSampleCompression) ? SamplerOptions | F_WSMP_NO_COMPRESSION          SamplerOptions = (NoSampleCompression) ? SamplerOptions | F_WSMP_NO_COMPRESSION
489                                                 : SamplerOptions & (~F_WSMP_NO_COMPRESSION);                                                 : SamplerOptions & (~F_WSMP_NO_COMPRESSION);
490            memcpy(&pData[4], &UnityNote, 2);
491            memcpy(&pData[6], &FineTune, 2);
492            memcpy(&pData[8], &Gain, 4);
493            memcpy(&pData[12], &SamplerOptions, 4);
494            memcpy(&pData[16], &SampleLoops, 4);
495          // update loop definitions          // update loop definitions
496          for (uint32_t i = 0; i < SampleLoops; i++) {          for (uint32_t i = 0; i < SampleLoops; i++) {
497              //FIXME: this does not handle extended loop structs correctly              //FIXME: this does not handle extended loop structs correctly
498              memccpy(&pData[uiHeaderSize + i * 16], pSampleLoops + i, 4, 4);              memcpy(&pData[uiHeaderSize + i * 16], pSampleLoops + i, 4 * 4);
499          }          }
500      }      }
501    
# Line 500  namespace DLS { Line 534  namespace DLS {
534              // PCM format specific              // PCM format specific
535              if (FormatTag == WAVE_FORMAT_PCM) {              if (FormatTag == WAVE_FORMAT_PCM) {
536                  BitDepth     = pCkFormat->ReadUint16();                  BitDepth     = pCkFormat->ReadUint16();
537                  FrameSize    = (FormatTag == WAVE_FORMAT_PCM) ? (BitDepth / 8) * Channels                  FrameSize    = (BitDepth / 8) * Channels;
                                                             : 0;  
538              } else { // unsupported sample data format              } else { // unsupported sample data format
539                  BitDepth     = 0;                  BitDepth     = 0;
540                  FrameSize    = 0;                  FrameSize    = 0;
# Line 701  namespace DLS { Line 734  namespace DLS {
734          if (!pCkFormat) pCkFormat = pWaveList->AddSubChunk(CHUNK_ID_FMT, 16); // assumes PCM format          if (!pCkFormat) pCkFormat = pWaveList->AddSubChunk(CHUNK_ID_FMT, 16); // assumes PCM format
735          uint8_t* pData = (uint8_t*) pCkFormat->LoadChunkData();          uint8_t* pData = (uint8_t*) pCkFormat->LoadChunkData();
736          // update 'fmt' chunk          // update 'fmt' chunk
737          memccpy(&pData[0], &FormatTag, 1, 2);          memcpy(&pData[0], &FormatTag, 2);
738          memccpy(&pData[2], &Channels,  1, 2);          memcpy(&pData[2], &Channels,  2);
739          memccpy(&pData[4], &SamplesPerSecond, 1, 4);          memcpy(&pData[4], &SamplesPerSecond, 4);
740          memccpy(&pData[8], &AverageBytesPerSecond, 1, 4);          memcpy(&pData[8], &AverageBytesPerSecond, 4);
741          memccpy(&pData[12], &BlockAlign, 1, 2);          memcpy(&pData[12], &BlockAlign, 2);
742          memccpy(&pData[14], &BitDepth, 1, 2); // assuming PCM format          memcpy(&pData[14], &BitDepth, 2); // assuming PCM format
743      }      }
744    
745    
# Line 798  namespace DLS { Line 831  namespace DLS {
831      void Region::UpdateChunks() {      void Region::UpdateChunks() {
832          // make sure 'rgnh' chunk exists          // make sure 'rgnh' chunk exists
833          RIFF::Chunk* rgnh = pCkRegion->GetSubChunk(CHUNK_ID_RGNH);          RIFF::Chunk* rgnh = pCkRegion->GetSubChunk(CHUNK_ID_RGNH);
834          if (!rgnh) rgnh = pCkRegion->AddSubChunk(CHUNK_ID_RGNH, 14);          if (!rgnh) rgnh = pCkRegion->AddSubChunk(CHUNK_ID_RGNH, Layer ? 14 : 12);
835          uint8_t* pData = (uint8_t*) rgnh->LoadChunkData();          uint8_t* pData = (uint8_t*) rgnh->LoadChunkData();
836          FormatOptionFlags = (SelfNonExclusive)          FormatOptionFlags = (SelfNonExclusive)
837                                  ? FormatOptionFlags | F_RGN_OPTION_SELFNONEXCLUSIVE                                  ? FormatOptionFlags | F_RGN_OPTION_SELFNONEXCLUSIVE
838                                  : FormatOptionFlags & (~F_RGN_OPTION_SELFNONEXCLUSIVE);                                  : FormatOptionFlags & (~F_RGN_OPTION_SELFNONEXCLUSIVE);
839          // update 'rgnh' chunk          // update 'rgnh' chunk
840          memccpy(&pData[0], &KeyRange, 2, 2);          memcpy(&pData[0], &KeyRange, 2 * 2);
841          memccpy(&pData[4], &VelocityRange, 2, 2);          memcpy(&pData[4], &VelocityRange, 2 * 2);
842          memccpy(&pData[8], &FormatOptionFlags, 1, 2);          memcpy(&pData[8], &FormatOptionFlags, 2);
843          memccpy(&pData[10], &KeyGroup, 1, 2);          memcpy(&pData[10], &KeyGroup, 2);
844          memccpy(&pData[12], &Layer, 1, 2);          if (rgnh->GetSize() >= 14) memcpy(&pData[12], &Layer, 2);
845    
846          // update chunks of base classes as well          // update chunks of base classes as well (but skip Resource,
847          Resource::UpdateChunks();          // as a rgn doesn't seem to have dlid and INFO chunks)
848          Articulator::UpdateChunks();          Articulator::UpdateChunks();
849          Sampler::UpdateChunks();          Sampler::UpdateChunks();
850    
# Line 841  namespace DLS { Line 874  namespace DLS {
874          if (index < 0) throw Exception("Could not save Region, could not find Region's sample");          if (index < 0) throw Exception("Could not save Region, could not find Region's sample");
875          WavePoolTableIndex = index;          WavePoolTableIndex = index;
876          // update 'wlnk' chunk          // update 'wlnk' chunk
877          memccpy(&pData[0], &WaveLinkOptionFlags, 1, 2);          memcpy(&pData[0], &WaveLinkOptionFlags, 2);
878          memccpy(&pData[2], &PhaseGroup, 1, 2);          memcpy(&pData[2], &PhaseGroup, 2);
879          memccpy(&pData[4], &Channel, 1, 4);          memcpy(&pData[4], &Channel, 4);
880          memccpy(&pData[8], &WavePoolTableIndex, 1, 4);          memcpy(&pData[8], &WavePoolTableIndex, 4);
881      }      }
882    
883    
# Line 957  namespace DLS { Line 990  namespace DLS {
990          locale.bank       = MIDI_BANK_ENCODE(MIDIBankCoarse, MIDIBankFine);          locale.bank       = MIDI_BANK_ENCODE(MIDIBankCoarse, MIDIBankFine);
991          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);
992          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
993          memccpy(&pData[0], &Regions, 1, 4);          memcpy(&pData[0], &Regions, 4);
994          memccpy(&pData[4], &locale, 2, 4);          memcpy(&pData[4], &locale, 2 * 4);
995          // update Region's chunks          // update Region's chunks
996          if (!pRegions) return;          if (!pRegions) return;
997          RegionList::iterator iter = pRegions->begin();          RegionList::iterator iter = pRegions->begin();
# Line 1254  namespace DLS { Line 1287  namespace DLS {
1287              RIFF::Chunk* ckVersion    = pRIFF->GetSubChunk(CHUNK_ID_VERS);              RIFF::Chunk* ckVersion    = pRIFF->GetSubChunk(CHUNK_ID_VERS);
1288              if (!ckVersion) ckVersion = pRIFF->AddSubChunk(CHUNK_ID_VERS, 8);              if (!ckVersion) ckVersion = pRIFF->AddSubChunk(CHUNK_ID_VERS, 8);
1289              uint8_t* pData = (uint8_t*) ckVersion->LoadChunkData();              uint8_t* pData = (uint8_t*) ckVersion->LoadChunkData();
1290              memccpy(pData, pVersion, 2, 4);              memcpy(pData, pVersion, 2 * 4);
1291          }          }
1292    
1293          // update 'colh' chunk          // update 'colh' chunk
# Line 1262  namespace DLS { Line 1295  namespace DLS {
1295          RIFF::Chunk* colh = pRIFF->GetSubChunk(CHUNK_ID_COLH);          RIFF::Chunk* colh = pRIFF->GetSubChunk(CHUNK_ID_COLH);
1296          if (!colh)   colh = pRIFF->AddSubChunk(CHUNK_ID_COLH, 4);          if (!colh)   colh = pRIFF->AddSubChunk(CHUNK_ID_COLH, 4);
1297          uint8_t* pData = (uint8_t*) colh->LoadChunkData();          uint8_t* pData = (uint8_t*) colh->LoadChunkData();
1298          memccpy(pData, &Instruments, 1, 4);          memcpy(pData, &Instruments, 4);
1299    
1300          // update instrument's chunks          // update instrument's chunks
1301          if (pInstruments) {          if (pInstruments) {
# Line 1282  namespace DLS { Line 1315  namespace DLS {
1315          ptbl->Resize(iPtblSize);          ptbl->Resize(iPtblSize);
1316          pData = (uint8_t*) ptbl->LoadChunkData();          pData = (uint8_t*) ptbl->LoadChunkData();
1317          WavePoolCount = iSamples;          WavePoolCount = iSamples;
1318          memccpy(&pData[4], &WavePoolCount, 1, 4);          memcpy(&pData[4], &WavePoolCount, 4);
1319          // 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()
1320          memset(&pData[WavePoolHeaderSize], 0, iPtblSize - WavePoolHeaderSize);          memset(&pData[WavePoolHeaderSize], 0, iPtblSize - WavePoolHeaderSize);
1321    

Legend:
Removed from v.902  
changed lines
  Added in v.928

  ViewVC Help
Powered by ViewVC