/[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 928 by persson, Tue Oct 24 19:32:47 2006 UTC revision 1155 by schoenebeck, Wed Apr 11 18:11:09 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 269  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 294  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 356  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()+1 : Software.length()+1) : 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(""), 128);          SaveString(CHUNK_ID_ISBJ, lstINFO, Subject, String(""), UseFixedLengthStrings, 128);
361      }      }
362    
363    
# Line 499  namespace DLS { Line 481  namespace DLS {
481          }          }
482      }      }
483    
484        /**
485         * Adds a new sample loop with the provided loop definition.
486         *
487         * @param - points to a loop definition that is to be copied
488         */
489        void Sampler::AddSampleLoop(sample_loop_t* pLoopDef) {
490            sample_loop_t* pNewLoops = new sample_loop_t[SampleLoops + 1];
491            // copy old loops array
492            for (int i = 0; i < SampleLoops; i++) {
493                pNewLoops[i] = pSampleLoops[i];
494            }
495            // add the new loop
496            pNewLoops[SampleLoops] = *pLoopDef;
497            // auto correct size field
498            pNewLoops[SampleLoops].Size = sizeof(DLS::sample_loop_t);
499            // free the old array and update the member variables
500            if (SampleLoops) delete[] pSampleLoops;
501            pSampleLoops = pNewLoops;
502            SampleLoops++;
503        }
504    
505        /**
506         * Deletes an existing sample loop.
507         *
508         * @param pLoopDef - pointer to existing loop definition
509         * @throws Exception - if given loop definition does not exist
510         */
511        void Sampler::DeleteSampleLoop(sample_loop_t* pLoopDef) {
512            sample_loop_t* pNewLoops = new sample_loop_t[SampleLoops - 1];
513            // copy old loops array (skipping given loop)
514            for (int i = 0, o = 0; i < SampleLoops; i++) {
515                if (&pSampleLoops[i] == pLoopDef) continue;
516                if (o == SampleLoops - 1)
517                    throw Exception("Could not delete Sample Loop, because it does not exist");
518                pNewLoops[o] = pSampleLoops[i];
519                o++;
520            }
521            // free the old array and update the member variables
522            if (SampleLoops) delete[] pSampleLoops;
523            pSampleLoops = pNewLoops;
524            SampleLoops--;
525        }
526    
527    
528    
529  // *************** Sample ***************  // *************** Sample ***************
# Line 532  namespace DLS { Line 557  namespace DLS {
557              AverageBytesPerSecond  = pCkFormat->ReadUint32();              AverageBytesPerSecond  = pCkFormat->ReadUint32();
558              BlockAlign             = pCkFormat->ReadUint16();              BlockAlign             = pCkFormat->ReadUint16();
559              // PCM format specific              // PCM format specific
560              if (FormatTag == WAVE_FORMAT_PCM) {              if (FormatTag == DLS_WAVE_FORMAT_PCM) {
561                  BitDepth     = pCkFormat->ReadUint16();                  BitDepth     = pCkFormat->ReadUint16();
562                  FrameSize    = (BitDepth / 8) * Channels;                  FrameSize    = (BitDepth / 8) * Channels;
563              } else { // unsupported sample data format              } else { // unsupported sample data format
# Line 540  namespace DLS { Line 565  namespace DLS {
565                  FrameSize    = 0;                  FrameSize    = 0;
566              }              }
567          } else { // 'fmt' chunk missing          } else { // 'fmt' chunk missing
568              FormatTag              = WAVE_FORMAT_PCM;              FormatTag              = DLS_WAVE_FORMAT_PCM;
569              BitDepth               = 16;              BitDepth               = 16;
570              Channels               = 1;              Channels               = 1;
571              SamplesPerSecond       = 44100;              SamplesPerSecond       = 44100;
# Line 548  namespace DLS { Line 573  namespace DLS {
573              FrameSize              = (BitDepth / 8) * Channels;              FrameSize              = (BitDepth / 8) * Channels;
574              BlockAlign             = FrameSize;              BlockAlign             = FrameSize;
575          }          }
576          SamplesTotal = (pCkData) ? (FormatTag == WAVE_FORMAT_PCM) ? pCkData->GetSize() / FrameSize          SamplesTotal = (pCkData) ? (FormatTag == DLS_WAVE_FORMAT_PCM) ? pCkData->GetSize() / FrameSize
577                                                                    : 0                                                                        : 0
578                                   : 0;                                   : 0;
579      }      }
580    
# Line 609  namespace DLS { Line 634  namespace DLS {
634       * the RIFF chunk which encapsulates the sample's wave data. The       * the RIFF chunk which encapsulates the sample's wave data. The
635       * returned value is dependant to the current FrameSize value.       * returned value is dependant to the current FrameSize value.
636       *       *
637       * @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
638       * @see FrameSize, FormatTag       * @see FrameSize, FormatTag
639       */       */
640      unsigned long Sample::GetSize() {      unsigned long Sample::GetSize() {
641          if (FormatTag != WAVE_FORMAT_PCM) return 0;          if (FormatTag != DLS_WAVE_FORMAT_PCM) return 0;
642          return (pCkData) ? pCkData->GetSize() / FrameSize : 0;          return (pCkData) ? pCkData->GetSize() / FrameSize : 0;
643      }      }
644    
# Line 635  namespace DLS { Line 660  namespace DLS {
660       * calling File::Save() as this might exceed the current sample's       * calling File::Save() as this might exceed the current sample's
661       * boundary!       * boundary!
662       *       *
663       * Also note: only WAVE_FORMAT_PCM is currently supported, that is       * Also note: only DLS_WAVE_FORMAT_PCM is currently supported, that is
664       * FormatTag must be WAVE_FORMAT_PCM. Trying to resize samples with       * FormatTag must be DLS_WAVE_FORMAT_PCM. Trying to resize samples with
665       * other formats will fail!       * other formats will fail!
666       *       *
667       * @param iNewSize - new sample wave data size in sample points (must be       * @param iNewSize - new sample wave data size in sample points (must be
668       *                   greater than zero)       *                   greater than zero)
669       * @throws Excecption if FormatTag != WAVE_FORMAT_PCM       * @throws Excecption if FormatTag != DLS_WAVE_FORMAT_PCM
670       * @throws Exception if \a iNewSize is less than 1       * @throws Exception if \a iNewSize is less than 1
671       * @see File::Save(), FrameSize, FormatTag       * @see File::Save(), FrameSize, FormatTag
672       */       */
673      void Sample::Resize(int iNewSize) {      void Sample::Resize(int iNewSize) {
674          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");
675          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");
676          const int iSizeInBytes = iNewSize * FrameSize;          const int iSizeInBytes = iNewSize * FrameSize;
677          pCkData = pWaveList->GetSubChunk(CHUNK_ID_DATA);          pCkData = pWaveList->GetSubChunk(CHUNK_ID_DATA);
# Line 659  namespace DLS { Line 684  namespace DLS {
684       * 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
685       * the sample into RAM, thus for disk streaming.       * the sample into RAM, thus for disk streaming.
686       *       *
687       * Also note: only WAVE_FORMAT_PCM is currently supported, that is       * Also note: only DLS_WAVE_FORMAT_PCM is currently supported, that is
688       * FormatTag must be WAVE_FORMAT_PCM. Trying to reposition the sample       * FormatTag must be DLS_WAVE_FORMAT_PCM. Trying to reposition the sample
689       * with other formats will fail!       * with other formats will fail!
690       *       *
691       * @param SampleCount  number of sample points       * @param SampleCount  number of sample points
692       * @param Whence       to which relation \a SampleCount refers to       * @param Whence       to which relation \a SampleCount refers to
693       * @returns new position within the sample, 0 if       * @returns new position within the sample, 0 if
694       *          FormatTag != WAVE_FORMAT_PCM       *          FormatTag != DLS_WAVE_FORMAT_PCM
695       * @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
696       * @see FrameSize, FormatTag       * @see FrameSize, FormatTag
697       */       */
698      unsigned long Sample::SetPos(unsigned long SampleCount, RIFF::stream_whence_t Whence) {      unsigned long Sample::SetPos(unsigned long SampleCount, RIFF::stream_whence_t Whence) {
699          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
700          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");
701          unsigned long orderedBytes = SampleCount * FrameSize;          unsigned long orderedBytes = SampleCount * FrameSize;
702          unsigned long result = pCkData->SetPos(orderedBytes, Whence);          unsigned long result = pCkData->SetPos(orderedBytes, Whence);
# Line 689  namespace DLS { Line 714  namespace DLS {
714       * @param SampleCount  number of sample points to read       * @param SampleCount  number of sample points to read
715       */       */
716      unsigned long Sample::Read(void* pBuffer, unsigned long SampleCount) {      unsigned long Sample::Read(void* pBuffer, unsigned long SampleCount) {
717          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
718          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?
719      }      }
720    
# Line 709  namespace DLS { Line 734  namespace DLS {
734       * @see LoadSampleData()       * @see LoadSampleData()
735       */       */
736      unsigned long Sample::Write(void* pBuffer, unsigned long SampleCount) {      unsigned long Sample::Write(void* pBuffer, unsigned long SampleCount) {
737          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
738          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");
739          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?
740      }      }
# Line 718  namespace DLS { Line 743  namespace DLS {
743       * Apply sample and its settings to the respective RIFF chunks. You have       * Apply sample and its settings to the respective RIFF chunks. You have
744       * to call File::Save() to make changes persistent.       * to call File::Save() to make changes persistent.
745       *       *
746       * @throws Exception if FormatTag != WAVE_FORMAT_PCM or no sample data       * @throws Exception if FormatTag != DLS_WAVE_FORMAT_PCM or no sample data
747       *                   was provided yet       *                   was provided yet
748       */       */
749      void Sample::UpdateChunks() {      void Sample::UpdateChunks() {
750          if (FormatTag != WAVE_FORMAT_PCM)          if (FormatTag != DLS_WAVE_FORMAT_PCM)
751              throw Exception("Could not save sample, only PCM format is supported");              throw Exception("Could not save sample, only PCM format is supported");
752          // 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
753          if (!pCkData)          if (!pCkData)
# Line 960  namespace DLS { Line 985  namespace DLS {
985          return pNewRegion;          return pNewRegion;
986      }      }
987    
988        void Instrument::MoveRegion(Region* pSrc, Region* pDst) {
989            RIFF::List* lrgn = pCkInstrument->GetSubList(LIST_TYPE_LRGN);
990            lrgn->MoveSubChunk(pSrc->pCkRegion, pDst ? pDst->pCkRegion : 0);
991    
992            pRegions->remove(pSrc);
993            RegionList::iterator iter = find(pRegions->begin(), pRegions->end(), pDst);
994            pRegions->insert(iter, pSrc);
995        }
996    
997      void Instrument::DeleteRegion(Region* pRegion) {      void Instrument::DeleteRegion(Region* pRegion) {
998          if (!pRegions) return;          if (!pRegions) return;
999          RegionList::iterator iter = find(pRegions->begin(), pRegions->end(), pRegion);          RegionList::iterator iter = find(pRegions->begin(), pRegions->end(), pRegion);

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

  ViewVC Help
Powered by ViewVC