/[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 918 by persson, Sat Sep 2 08:45:37 2006 UTC revision 1050 by schoenebeck, Fri Mar 2 01:04:45 2007 UTC
# Line 1  Line 1 
1  /***************************************************************************  /***************************************************************************
2   *                                                                         *   *                                                                         *
3   *   libgig - C++ cross-platform Gigasampler format file loader library    *   *   libgig - C++ cross-platform Gigasampler format file access library    *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003-2005 by Christian Schoenebeck                      *   *   Copyright (C) 2003-2007 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 228  namespace DLS { Line 228  namespace DLS {
228    
229      /** @brief Constructor.      /** @brief Constructor.
230       *       *
231       * Initializes the info strings with values provided by a INFO list chunk.       * Initializes the info strings with values provided by an INFO list chunk.
232       *       *
233       * @param list - pointer to a list chunk which contains a INFO list chunk       * @param list - pointer to a list chunk which contains an INFO list chunk
234       */       */
235      Info::Info(RIFF::List* list) {      Info::Info(RIFF::List* list) {
236          UseFixedLengthStrings = false;          UseFixedLengthStrings = false;
# Line 254  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 268  namespace DLS { Line 269  namespace DLS {
269       */       */
270      void Info::LoadString(uint32_t ChunkID, RIFF::List* lstINFO, String& s) {      void Info::LoadString(uint32_t ChunkID, RIFF::List* lstINFO, String& s) {
271          RIFF::Chunk* ck = lstINFO->GetSubChunk(ChunkID);          RIFF::Chunk* ck = lstINFO->GetSubChunk(ChunkID);
272          if (ck) {          ::LoadString(ck, s); // function from helper.h
             const char* str = (char*)ck->LoadChunkData();  
             int size = ck->GetSize();  
             int len;  
             for (len = 0 ; len < size ; len++)  
                 if (str[len] == '\0') break;  
             s.assign(str, len);  
             ck->ReleaseChunkData();  
         }  
273      }      }
274    
275      /** @brief Apply given INFO field to the respective chunk.      /** @brief Apply given INFO field to the respective chunk.
# Line 293  namespace DLS { Line 286  namespace DLS {
286       * @param lstINFO  - parent (INFO) RIFF list chunk       * @param lstINFO  - parent (INFO) RIFF list chunk
287       * @param s        - current value of info field       * @param s        - current value of info field
288       * @param sDefault - default value       * @param sDefault - default value
289       * @param size     - wanted size of the INFO chunk. This is ignored if UseFixedLengthStrings is false.       * @param bUseFixedLengthStrings - should a specific string size be forced in the chunk?
290         * @param size     - wanted size of the INFO chunk. This is ignored if bUseFixedLengthStrings is false.
291       */       */
292      void Info::SaveString(uint32_t ChunkID, RIFF::List* lstINFO, const String& s, const String& sDefault, int size) {      void Info::SaveString(uint32_t ChunkID, RIFF::List* lstINFO, const String& s, const String& sDefault, bool bUseFixedLengthStrings, int size) {
293          RIFF::Chunk* ck = lstINFO->GetSubChunk(ChunkID);          RIFF::Chunk* ck = lstINFO->GetSubChunk(ChunkID);
294          if (ck) { // if chunk exists already, use 's' as value          ::SaveString(ChunkID, ck, lstINFO, s, sDefault, bUseFixedLengthStrings, size); // function from helper.h
             if (!UseFixedLengthStrings) size = s.size() + 1;  
             ck->Resize(size);  
             char* pData = (char*) ck->LoadChunkData();  
             strncpy(pData, s.c_str(), size);  
         } else if (s != "" || sDefault != "") { // create chunk  
             const String& sToSave = (s != "") ? s : sDefault;  
             if (!UseFixedLengthStrings) size = sToSave.size() + 1;  
             ck = lstINFO->AddSubChunk(ChunkID, size);  
             char* pData = (char*) ck->LoadChunkData();  
             strncpy(pData, sToSave.c_str(), size);  
         }  
295      }      }
296    
297      /** @brief Update chunks with current info values.      /** @brief Update chunks with current info values.
# Line 355  namespace DLS { Line 338  namespace DLS {
338    
339          // (the string size values are for gig files; they are only          // (the string size values are for gig files; they are only
340          // used if UseFixedLengthStrings is set to true)          // used if UseFixedLengthStrings is set to true)
341          SaveString(CHUNK_ID_INAM, lstINFO, Name, defaultName,          SaveString(CHUNK_ID_INAM, lstINFO, Name, defaultName, UseFixedLengthStrings,
342                     resourceType == RIFF_TYPE_DLS ? 128 : 64);                     resourceType == RIFF_TYPE_DLS ? 128 : 64);
343          SaveString(CHUNK_ID_IARL, lstINFO, ArchivalLocation, String(""), 256);          SaveString(CHUNK_ID_IARL, lstINFO, ArchivalLocation, String(""), UseFixedLengthStrings, 256);
344          SaveString(CHUNK_ID_ICRD, lstINFO, CreationDate, defaultCreationDate, 128);          SaveString(CHUNK_ID_ICRD, lstINFO, CreationDate, defaultCreationDate, UseFixedLengthStrings, 128);
345          SaveString(CHUNK_ID_ICMT, lstINFO, Comments, defaultComments, 1024);          SaveString(CHUNK_ID_ICMT, lstINFO, Comments, defaultComments, UseFixedLengthStrings, 1024);
346          SaveString(CHUNK_ID_IPRD, lstINFO, Product, String(""), 128);          SaveString(CHUNK_ID_IPRD, lstINFO, Product, String(""), UseFixedLengthStrings, 128);
347          SaveString(CHUNK_ID_ICOP, lstINFO, Copyright, String(""), 128);          SaveString(CHUNK_ID_ICOP, lstINFO, Copyright, String(""), UseFixedLengthStrings, 128);
348          SaveString(CHUNK_ID_IART, lstINFO, Artists, String(""), 128);          SaveString(CHUNK_ID_IART, lstINFO, Artists, String(""), UseFixedLengthStrings, 128);
349          SaveString(CHUNK_ID_IGNR, lstINFO, Genre, String(""), 128);          SaveString(CHUNK_ID_IGNR, lstINFO, Genre, String(""), UseFixedLengthStrings, 128);
350          SaveString(CHUNK_ID_IKEY, lstINFO, Keywords, String(""), 128);          SaveString(CHUNK_ID_IKEY, lstINFO, Keywords, String(""), UseFixedLengthStrings, 128);
351          SaveString(CHUNK_ID_IENG, lstINFO, Engineer, String(""), 128);          SaveString(CHUNK_ID_IENG, lstINFO, Engineer, String(""), UseFixedLengthStrings, 128);
352          SaveString(CHUNK_ID_ITCH, lstINFO, Technician, String(""), 128);          SaveString(CHUNK_ID_ITCH, lstINFO, Technician, String(""), UseFixedLengthStrings, 128);
353          SaveString(CHUNK_ID_ISFT, lstINFO, Software, defaultSoftware,          SaveString(CHUNK_ID_ISFT, lstINFO, Software, defaultSoftware, UseFixedLengthStrings,
354                     resourceType == LIST_TYPE_INS ?                     resourceType == LIST_TYPE_INS ?
355                     (Software == "" ? defaultSoftware.length() : Software.length()) : 128);                     (Software == "" ? defaultSoftware.length() : Software.length()) : 128);
356          SaveString(CHUNK_ID_IMED, lstINFO, Medium, String(""), 128);          SaveString(CHUNK_ID_IMED, lstINFO, Medium, String(""), UseFixedLengthStrings, 128);
357          SaveString(CHUNK_ID_ISRC, lstINFO, Source, String(""), 128);          SaveString(CHUNK_ID_ISRC, lstINFO, Source, String(""), UseFixedLengthStrings, 128);
358          SaveString(CHUNK_ID_ISRF, lstINFO, SourceForm, String(""), 128);          SaveString(CHUNK_ID_ISRF, lstINFO, SourceForm, String(""), UseFixedLengthStrings, 128);
359          SaveString(CHUNK_ID_ICMS, lstINFO, Commissioned, String(""), 128);          SaveString(CHUNK_ID_ICMS, lstINFO, Commissioned, String(""), UseFixedLengthStrings, 128);
360            SaveString(CHUNK_ID_ISBJ, lstINFO, Subject, String(""), UseFixedLengthStrings, 128);
361      }      }
362    
363    
# Line 485  namespace DLS { Line 469  namespace DLS {
469                                                     : SamplerOptions & (~F_WSMP_NO_TRUNCATION);                                                     : SamplerOptions & (~F_WSMP_NO_TRUNCATION);
470          SamplerOptions = (NoSampleCompression) ? SamplerOptions | F_WSMP_NO_COMPRESSION          SamplerOptions = (NoSampleCompression) ? SamplerOptions | F_WSMP_NO_COMPRESSION
471                                                 : SamplerOptions & (~F_WSMP_NO_COMPRESSION);                                                 : SamplerOptions & (~F_WSMP_NO_COMPRESSION);
472            memcpy(&pData[4], &UnityNote, 2);
473            memcpy(&pData[6], &FineTune, 2);
474            memcpy(&pData[8], &Gain, 4);
475            memcpy(&pData[12], &SamplerOptions, 4);
476            memcpy(&pData[16], &SampleLoops, 4);
477          // update loop definitions          // update loop definitions
478          for (uint32_t i = 0; i < SampleLoops; i++) {          for (uint32_t i = 0; i < SampleLoops; i++) {
479              //FIXME: this does not handle extended loop structs correctly              //FIXME: this does not handle extended loop structs correctly
# Line 525  namespace DLS { Line 514  namespace DLS {
514              AverageBytesPerSecond  = pCkFormat->ReadUint32();              AverageBytesPerSecond  = pCkFormat->ReadUint32();
515              BlockAlign             = pCkFormat->ReadUint16();              BlockAlign             = pCkFormat->ReadUint16();
516              // PCM format specific              // PCM format specific
517              if (FormatTag == WAVE_FORMAT_PCM) {              if (FormatTag == DLS_WAVE_FORMAT_PCM) {
518                  BitDepth     = pCkFormat->ReadUint16();                  BitDepth     = pCkFormat->ReadUint16();
519                  FrameSize    = (FormatTag == WAVE_FORMAT_PCM) ? (BitDepth / 8) * Channels                  FrameSize    = (BitDepth / 8) * Channels;
                                                             : 0;  
520              } else { // unsupported sample data format              } else { // unsupported sample data format
521                  BitDepth     = 0;                  BitDepth     = 0;
522                  FrameSize    = 0;                  FrameSize    = 0;
523              }              }
524          } else { // 'fmt' chunk missing          } else { // 'fmt' chunk missing
525              FormatTag              = WAVE_FORMAT_PCM;              FormatTag              = DLS_WAVE_FORMAT_PCM;
526              BitDepth               = 16;              BitDepth               = 16;
527              Channels               = 1;              Channels               = 1;
528              SamplesPerSecond       = 44100;              SamplesPerSecond       = 44100;
# Line 542  namespace DLS { Line 530  namespace DLS {
530              FrameSize              = (BitDepth / 8) * Channels;              FrameSize              = (BitDepth / 8) * Channels;
531              BlockAlign             = FrameSize;              BlockAlign             = FrameSize;
532          }          }
533          SamplesTotal = (pCkData) ? (FormatTag == WAVE_FORMAT_PCM) ? pCkData->GetSize() / FrameSize          SamplesTotal = (pCkData) ? (FormatTag == DLS_WAVE_FORMAT_PCM) ? pCkData->GetSize() / FrameSize
534                                                                    : 0                                                                        : 0
535                                   : 0;                                   : 0;
536      }      }
537    
# Line 603  namespace DLS { Line 591  namespace DLS {
591       * the RIFF chunk which encapsulates the sample's wave data. The       * the RIFF chunk which encapsulates the sample's wave data. The
592       * returned value is dependant to the current FrameSize value.       * returned value is dependant to the current FrameSize value.
593       *       *
594       * @returns number of sample points or 0 if FormatTag != WAVE_FORMAT_PCM       * @returns number of sample points or 0 if FormatTag != DLS_WAVE_FORMAT_PCM
595       * @see FrameSize, FormatTag       * @see FrameSize, FormatTag
596       */       */
597      unsigned long Sample::GetSize() {      unsigned long Sample::GetSize() {
598          if (FormatTag != WAVE_FORMAT_PCM) return 0;          if (FormatTag != DLS_WAVE_FORMAT_PCM) return 0;
599          return (pCkData) ? pCkData->GetSize() / FrameSize : 0;          return (pCkData) ? pCkData->GetSize() / FrameSize : 0;
600      }      }
601    
# Line 629  namespace DLS { Line 617  namespace DLS {
617       * calling File::Save() as this might exceed the current sample's       * calling File::Save() as this might exceed the current sample's
618       * boundary!       * boundary!
619       *       *
620       * Also note: only WAVE_FORMAT_PCM is currently supported, that is       * Also note: only DLS_WAVE_FORMAT_PCM is currently supported, that is
621       * FormatTag must be WAVE_FORMAT_PCM. Trying to resize samples with       * FormatTag must be DLS_WAVE_FORMAT_PCM. Trying to resize samples with
622       * other formats will fail!       * other formats will fail!
623       *       *
624       * @param iNewSize - new sample wave data size in sample points (must be       * @param iNewSize - new sample wave data size in sample points (must be
625       *                   greater than zero)       *                   greater than zero)
626       * @throws Excecption if FormatTag != WAVE_FORMAT_PCM       * @throws Excecption if FormatTag != DLS_WAVE_FORMAT_PCM
627       * @throws Exception if \a iNewSize is less than 1       * @throws Exception if \a iNewSize is less than 1
628       * @see File::Save(), FrameSize, FormatTag       * @see File::Save(), FrameSize, FormatTag
629       */       */
630      void Sample::Resize(int iNewSize) {      void Sample::Resize(int iNewSize) {
631          if (FormatTag != WAVE_FORMAT_PCM) throw Exception("Sample's format is not WAVE_FORMAT_PCM");          if (FormatTag != DLS_WAVE_FORMAT_PCM) throw Exception("Sample's format is not DLS_WAVE_FORMAT_PCM");
632          if (iNewSize < 1) throw Exception("Sample size must be at least one sample point");          if (iNewSize < 1) throw Exception("Sample size must be at least one sample point");
633          const int iSizeInBytes = iNewSize * FrameSize;          const int iSizeInBytes = iNewSize * FrameSize;
634          pCkData = pWaveList->GetSubChunk(CHUNK_ID_DATA);          pCkData = pWaveList->GetSubChunk(CHUNK_ID_DATA);
# Line 653  namespace DLS { Line 641  namespace DLS {
641       * bytes). Use this method and <i>Read()</i> if you don't want to load       * bytes). Use this method and <i>Read()</i> if you don't want to load
642       * the sample into RAM, thus for disk streaming.       * the sample into RAM, thus for disk streaming.
643       *       *
644       * Also note: only WAVE_FORMAT_PCM is currently supported, that is       * Also note: only DLS_WAVE_FORMAT_PCM is currently supported, that is
645       * FormatTag must be WAVE_FORMAT_PCM. Trying to reposition the sample       * FormatTag must be DLS_WAVE_FORMAT_PCM. Trying to reposition the sample
646       * with other formats will fail!       * with other formats will fail!
647       *       *
648       * @param SampleCount  number of sample points       * @param SampleCount  number of sample points
649       * @param Whence       to which relation \a SampleCount refers to       * @param Whence       to which relation \a SampleCount refers to
650       * @returns new position within the sample, 0 if       * @returns new position within the sample, 0 if
651       *          FormatTag != WAVE_FORMAT_PCM       *          FormatTag != DLS_WAVE_FORMAT_PCM
652       * @throws Exception if no data RIFF chunk was created for the sample yet       * @throws Exception if no data RIFF chunk was created for the sample yet
653       * @see FrameSize, FormatTag       * @see FrameSize, FormatTag
654       */       */
655      unsigned long Sample::SetPos(unsigned long SampleCount, RIFF::stream_whence_t Whence) {      unsigned long Sample::SetPos(unsigned long SampleCount, RIFF::stream_whence_t Whence) {
656          if (FormatTag != WAVE_FORMAT_PCM) return 0; // failed: wave data not PCM format          if (FormatTag != DLS_WAVE_FORMAT_PCM) return 0; // failed: wave data not PCM format
657          if (!pCkData) throw Exception("No data chunk created for sample yet, call Sample::Resize() to create one");          if (!pCkData) throw Exception("No data chunk created for sample yet, call Sample::Resize() to create one");
658          unsigned long orderedBytes = SampleCount * FrameSize;          unsigned long orderedBytes = SampleCount * FrameSize;
659          unsigned long result = pCkData->SetPos(orderedBytes, Whence);          unsigned long result = pCkData->SetPos(orderedBytes, Whence);
# Line 683  namespace DLS { Line 671  namespace DLS {
671       * @param SampleCount  number of sample points to read       * @param SampleCount  number of sample points to read
672       */       */
673      unsigned long Sample::Read(void* pBuffer, unsigned long SampleCount) {      unsigned long Sample::Read(void* pBuffer, unsigned long SampleCount) {
674          if (FormatTag != WAVE_FORMAT_PCM) return 0; // failed: wave data not PCM format          if (FormatTag != DLS_WAVE_FORMAT_PCM) return 0; // failed: wave data not PCM format
675          return pCkData->Read(pBuffer, SampleCount, FrameSize); // FIXME: channel inversion due to endian correction?          return pCkData->Read(pBuffer, SampleCount, FrameSize); // FIXME: channel inversion due to endian correction?
676      }      }
677    
# Line 703  namespace DLS { Line 691  namespace DLS {
691       * @see LoadSampleData()       * @see LoadSampleData()
692       */       */
693      unsigned long Sample::Write(void* pBuffer, unsigned long SampleCount) {      unsigned long Sample::Write(void* pBuffer, unsigned long SampleCount) {
694          if (FormatTag != WAVE_FORMAT_PCM) return 0; // failed: wave data not PCM format          if (FormatTag != DLS_WAVE_FORMAT_PCM) return 0; // failed: wave data not PCM format
695          if (GetSize() < SampleCount) throw Exception("Could not write sample data, current sample size to small");          if (GetSize() < SampleCount) throw Exception("Could not write sample data, current sample size to small");
696          return pCkData->Write(pBuffer, SampleCount, FrameSize); // FIXME: channel inversion due to endian correction?          return pCkData->Write(pBuffer, SampleCount, FrameSize); // FIXME: channel inversion due to endian correction?
697      }      }
# Line 712  namespace DLS { Line 700  namespace DLS {
700       * Apply sample and its settings to the respective RIFF chunks. You have       * Apply sample and its settings to the respective RIFF chunks. You have
701       * to call File::Save() to make changes persistent.       * to call File::Save() to make changes persistent.
702       *       *
703       * @throws Exception if FormatTag != WAVE_FORMAT_PCM or no sample data       * @throws Exception if FormatTag != DLS_WAVE_FORMAT_PCM or no sample data
704       *                   was provided yet       *                   was provided yet
705       */       */
706      void Sample::UpdateChunks() {      void Sample::UpdateChunks() {
707          if (FormatTag != WAVE_FORMAT_PCM)          if (FormatTag != DLS_WAVE_FORMAT_PCM)
708              throw Exception("Could not save sample, only PCM format is supported");              throw Exception("Could not save sample, only PCM format is supported");
709          // we refuse to do anything if not sample wave form was provided yet          // we refuse to do anything if not sample wave form was provided yet
710          if (!pCkData)          if (!pCkData)

Legend:
Removed from v.918  
changed lines
  Added in v.1050

  ViewVC Help
Powered by ViewVC