/[svn]/libgig/trunk/src/gig.cpp
ViewVC logotype

Diff of /libgig/trunk/src/gig.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2912 by schoenebeck, Tue May 17 14:30:10 2016 UTC revision 2923 by schoenebeck, Sat May 21 08:54:32 2016 UTC
# Line 318  namespace { Line 318  namespace {
318  // *************** Sample ***************  // *************** Sample ***************
319  // *  // *
320    
321      unsigned int Sample::Instances = 0;      size_t       Sample::Instances = 0;
322      buffer_t     Sample::InternalDecompressionBuffer;      buffer_t     Sample::InternalDecompressionBuffer;
323    
324      /** @brief Constructor.      /** @brief Constructor.
# Line 789  namespace { Line 789  namespace {
789       * FormatTag must be DLS_WAVE_FORMAT_PCM. Trying to resize samples with       * FormatTag must be DLS_WAVE_FORMAT_PCM. Trying to resize samples with
790       * other formats will fail!       * other formats will fail!
791       *       *
792       * @param iNewSize - new sample wave data size in sample points (must be       * @param NewSize - new sample wave data size in sample points (must be
793       *                   greater than zero)       *                  greater than zero)
794       * @throws DLS::Excecption if FormatTag != DLS_WAVE_FORMAT_PCM       * @throws DLS::Excecption if FormatTag != DLS_WAVE_FORMAT_PCM
795       *                         or if \a iNewSize is less than 1       * @throws DLS::Exception if \a NewSize is less than 1 or unrealistic large
796       * @throws gig::Exception if existing sample is compressed       * @throws gig::Exception if existing sample is compressed
797       * @see DLS::Sample::GetSize(), DLS::Sample::FrameSize,       * @see DLS::Sample::GetSize(), DLS::Sample::FrameSize,
798       *      DLS::Sample::FormatTag, File::Save()       *      DLS::Sample::FormatTag, File::Save()
799       */       */
800      void Sample::Resize(int iNewSize) {      void Sample::Resize(file_offset_t NewSize) {
801          if (Compressed) throw gig::Exception("There is no support for modifying compressed samples (yet)");          if (Compressed) throw gig::Exception("There is no support for modifying compressed samples (yet)");
802          DLS::Sample::Resize(iNewSize);          DLS::Sample::Resize(NewSize);
803      }      }
804    
805      /**      /**
# Line 1357  namespace { Line 1357  namespace {
1357  // *************** DimensionRegion ***************  // *************** DimensionRegion ***************
1358  // *  // *
1359    
1360      uint                               DimensionRegion::Instances       = 0;      size_t                             DimensionRegion::Instances       = 0;
1361      DimensionRegion::VelocityTableMap* DimensionRegion::pVelocityTables = NULL;      DimensionRegion::VelocityTableMap* DimensionRegion::pVelocityTables = NULL;
1362    
1363      DimensionRegion::DimensionRegion(Region* pParent, RIFF::List* _3ewl) : DLS::Sampler(_3ewl) {      DimensionRegion::DimensionRegion(Region* pParent, RIFF::List* _3ewl) : DLS::Sampler(_3ewl) {
# Line 3106  namespace { Line 3106  namespace {
3106          int step = 1;          int step = 1;
3107          for (int i = 0 ; i < veldim ; i++) step <<= pDimensionDefinitions[i].bits;          for (int i = 0 ; i < veldim ; i++) step <<= pDimensionDefinitions[i].bits;
3108          int skipveldim = (step << pDimensionDefinitions[veldim].bits) - step;          int skipveldim = (step << pDimensionDefinitions[veldim].bits) - step;
         int end = step * pDimensionDefinitions[veldim].zones;  
3109    
3110          // loop through all dimension regions for all dimensions except the velocity dimension          // loop through all dimension regions for all dimensions except the velocity dimension
3111          int dim[8] = { 0 };          int dim[8] = { 0 };
3112          for (int i = 0 ; i < DimensionRegions ; i++) {          for (int i = 0 ; i < DimensionRegions ; i++) {
3113                const int end = i + step * pDimensionDefinitions[veldim].zones;
3114    
3115                // create a velocity table for all cases where the velocity zone is zero
3116              if (pDimensionRegions[i]->DimensionUpperLimits[veldim] ||              if (pDimensionRegions[i]->DimensionUpperLimits[veldim] ||
3117                  pDimensionRegions[i]->VelocityUpperLimit) {                  pDimensionRegions[i]->VelocityUpperLimit) {
3118                  // create the velocity table                  // create the velocity table
# Line 3142  namespace { Line 3143  namespace {
3143                  }                  }
3144              }              }
3145    
3146                // jump to the next case where the velocity zone is zero
3147              int j;              int j;
3148              int shift = 0;              int shift = 0;
3149              for (j = 0 ; j < Dimensions ; j++) {              for (j = 0 ; j < Dimensions ; j++) {
# Line 3850  namespace { Line 3852  namespace {
3852          if ((int32_t)WavePoolTableIndex == -1) return NULL;          if ((int32_t)WavePoolTableIndex == -1) return NULL;
3853          File* file = (File*) GetParent()->GetParent();          File* file = (File*) GetParent()->GetParent();
3854          if (!file->pWavePoolTable) return NULL;          if (!file->pWavePoolTable) return NULL;
3855          if (file->HasMonolithicLargeFilePolicy()) {          // for new files or files >= 2 GB use 64 bit wave pool offsets
3856            if (file->pRIFF->IsNew() || (file->pRIFF->GetCurrentFileSize() >> 31)) {
3857                // use 64 bit wave pool offsets (treating this as large file)
3858              uint64_t soughtoffset =              uint64_t soughtoffset =
3859                  uint64_t(file->pWavePoolTable[WavePoolTableIndex]) |                  uint64_t(file->pWavePoolTable[WavePoolTableIndex]) |
3860                  uint64_t(file->pWavePoolTableHi[WavePoolTableIndex]) << 32;                  uint64_t(file->pWavePoolTableHi[WavePoolTableIndex]) << 32;
# Line 3861  namespace { Line 3865  namespace {
3865                  sample = file->GetNextSample();                  sample = file->GetNextSample();
3866              }              }
3867          } else {          } else {
3868                // use extension files and 32 bit wave pool offsets
3869              file_offset_t soughtoffset = file->pWavePoolTable[WavePoolTableIndex];              file_offset_t soughtoffset = file->pWavePoolTable[WavePoolTableIndex];
3870              file_offset_t soughtfileno = file->pWavePoolTableHi[WavePoolTableIndex];              file_offset_t soughtfileno = file->pWavePoolTableHi[WavePoolTableIndex];
3871              Sample* sample = file->GetFirstSample(pProgress);              Sample* sample = file->GetFirstSample(pProgress);
# Line 5348  namespace { Line 5353  namespace {
5353          int iTotalSamples = WavePoolCount;          int iTotalSamples = WavePoolCount;
5354    
5355          // check if samples should be loaded from extension files          // check if samples should be loaded from extension files
5356            // (only for old gig files < 2 GB)
5357          int lastFileNo = 0;          int lastFileNo = 0;
5358          if (!HasMonolithicLargeFilePolicy()) {          if (!file->IsNew() && !(file->GetCurrentFileSize() >> 31)) {
5359              for (int i = 0 ; i < WavePoolCount ; i++) {              for (int i = 0 ; i < WavePoolCount ; i++) {
5360                  if (pWavePoolTableHi[i] > lastFileNo) lastFileNo = pWavePoolTableHi[i];                  if (pWavePoolTableHi[i] > lastFileNo) lastFileNo = pWavePoolTableHi[i];
5361              }              }
# Line 5841  namespace { Line 5847  namespace {
5847          }          }
5848      }      }
5849    
     /** @brief Returns the version number of libgig's Giga file format extension.  
      *  
      * libgig added several new features which were not available with the  
      * original GigaStudio software. For those purposes libgig's own custom RIFF  
      * chunks were added to the Giga file format.  
      *  
      * This method returns the version number of the Giga file format extension  
      * used in this Giga file. Currently there are 3 possible values that might  
      * be returned by this method:  
      *  
      * - @c 0: This gig file is not using any libgig specific file format  
      *         extension at all.  
      * - @c 1: This gig file uses the RT instrument script format extension.  
      * - @c 2: This gig file additionally provides support for monolithic  
      *         large gig files (larger than 2 GB).  
      *  
      * @note This method is currently protected and shall not be used as public  
      * API method, since its method signature might change in future.  
      */  
     uint File::GetFormatExtensionVersion() const {  
         RIFF::List* lst3LS = pRIFF->GetSubList(LIST_TYPE_3LS);  
         if (!lst3LS) return 0; // is not using custom Giga format extensions at all  
         RIFF::Chunk* ckFFmt = lst3LS->GetSubChunk(CHUNK_ID_FFMT);  
         if (!ckFFmt) return 1; // uses custom Giga format extension(s) but had no format version saved  
         uint8_t* pData = (uint8_t*) ckFFmt->LoadChunkData();  
         return load32(pData);  
     }  
   
     /** @brief Returns true in case this file is stored as one, single monolithic gig file.  
      *  
      * To avoid issues with operating systems which did not support large files  
      * (larger than 2 GB) the original Giga file format avoided to ever save gig  
      * files larger than 2 GB, instead such large Giga files were splitted into  
      * several files, each one not being larger than 2 GB. It used a predefined  
      * file name scheme for them like this:  
      * @code  
      * foo.gig  
      * foo.gx01  
      * foo.gx02  
      * foo.gx03  
      * ...  
      * @endcode  
      * So when like in this example foo.gig was loaded, all other files  
      * (foo.gx01, ...) were automatically loaded as well to make up the overall  
      * large gig file (provided they were located at the same directory). Such  
      * additional .gxYY files were called "extension files".  
      *  
      * Since nowadays all modern systems support large files, libgig always  
      * saves large gig files as one single monolithic gig file instead, that  
      * is libgig won't split such a large gig file into separate files like the  
      * original GigaStudio software did. It uses a custom Giga file format  
      * extension for this feature.  
      *  
      * For still being able though to load old splitted gig files and the new  
      * large monolithic ones, this method is used to determine which loading  
      * policy must be used for this gig file.  
      *  
      * @note This method is currently protected and shall not be used as public  
      * API method, since its method signature might change in future and since  
      * this method should not be directly relevant for applications based on  
      * libgig.  
      */  
     bool File::HasMonolithicLargeFilePolicy() const {  
         RIFF::List* lst3LS = pRIFF->GetSubList(LIST_TYPE_3LS);  
         if (!lst3LS) return false;  
         RIFF::Chunk* ckFFmt = lst3LS->GetSubChunk(CHUNK_ID_FFMT);  
         if (!ckFFmt) return false;  
         uint8_t* pData = (uint8_t*) ckFFmt->LoadChunkData();  
         uint32_t formatBitField = load32(&pData[4]);  
         return formatBitField & 1;  
     }  
   
5850      /**      /**
5851       * Apply all the gig file's current instruments, samples, groups and settings       * Apply all the gig file's current instruments, samples, groups and settings
5852       * to the respective RIFF chunks. You have to call Save() to make changes       * to the respective RIFF chunks. You have to call Save() to make changes
# Line 5927  namespace { Line 5861  namespace {
5861      void File::UpdateChunks(progress_t* pProgress) {      void File::UpdateChunks(progress_t* pProgress) {
5862          bool newFile = pRIFF->GetSubList(LIST_TYPE_INFO) == NULL;          bool newFile = pRIFF->GetSubList(LIST_TYPE_INFO) == NULL;
5863    
         b64BitWavePoolOffsets = pVersion && pVersion->major == 3;  
   
5864          // update own gig format extension chunks          // update own gig format extension chunks
5865          // (not part of the GigaStudio 4 format)          // (not part of the GigaStudio 4 format)
5866          RIFF::List* lst3LS = pRIFF->GetSubList(LIST_TYPE_3LS);          RIFF::List* lst3LS = pRIFF->GetSubList(LIST_TYPE_3LS);
# Line 5936  namespace { Line 5868  namespace {
5868              lst3LS = pRIFF->AddSubList(LIST_TYPE_3LS);              lst3LS = pRIFF->AddSubList(LIST_TYPE_3LS);
5869          }          }
5870          // Make sure <3LS > chunk is placed before <ptbl> chunk. The precise          // Make sure <3LS > chunk is placed before <ptbl> chunk. The precise
5871          // location of <3LS > is irrelevant, however it MUST BE located BEFORE          // location of <3LS > is irrelevant, however it should be located
5872          // the actual wave data, otherwise the <3LS > chunk becomes          // before  the actual wave data
         // inaccessible on gig files larger than 4GB !  
5873          RIFF::Chunk* ckPTBL = pRIFF->GetSubChunk(CHUNK_ID_PTBL);          RIFF::Chunk* ckPTBL = pRIFF->GetSubChunk(CHUNK_ID_PTBL);
5874          pRIFF->MoveSubChunk(lst3LS, ckPTBL);          pRIFF->MoveSubChunk(lst3LS, ckPTBL);
5875    
         // Update <FFmt> chunk with informations about our file format  
         // extensions. Currently this <FFmt> chunk has the following  
         // layout:  
         //  
         // <uint32> -> (libgig's) File Format Extension version  
         // <uint32> -> Format bit field:  
         //             bit 0: If flag is not set use separate .gx01  
         //                    extension files if file is larger than 2 GB  
         //                    like with the original Giga format, if flag  
         //                    is set use 64 bit sample references and keep  
         //                    everything as one single monolithic gig file.  
         RIFF::Chunk* ckFFmt = lst3LS->GetSubChunk(CHUNK_ID_FFMT);  
         if (!ckFFmt) {  
             const int iChunkSize = 2 * sizeof(uint32_t);  
             ckFFmt = lst3LS->AddSubChunk(CHUNK_ID_FFMT, iChunkSize);  
         }  
         {  
             uint8_t* pData = (uint8_t*) ckFFmt->LoadChunkData();  
             store32(&pData[0], GIG_FILE_EXT_VERSION);  
             // for now we always save gig files larger than 2 GB as one  
             // single monolithic file (saving those with extension files is  
             // currently not supported and probably also not desired anymore  
             // nowadays).  
             uint32_t formatBitfield = 1;  
             store32(&pData[4], formatBitfield);  
         }  
5876          // This must be performed before writing the chunks for instruments,          // This must be performed before writing the chunks for instruments,
5877          // because the instruments' script slots will write the file offsets          // because the instruments' script slots will write the file offsets
5878          // of the respective instrument script chunk as reference.          // of the respective instrument script chunk as reference.
# Line 5980  namespace { Line 5885  namespace {
5885              }              }
5886          }          }
5887    
5888            // in case no libgig custom format data was added, then remove the
5889            // custom "3LS " chunk again
5890            if (!lst3LS->CountSubChunks()) {
5891                pRIFF->DeleteSubChunk(lst3LS);
5892                lst3LS = NULL;
5893            }
5894    
5895          // first update base class's chunks          // first update base class's chunks
5896          DLS::File::UpdateChunks(pProgress);          DLS::File::UpdateChunks(pProgress);
5897    

Legend:
Removed from v.2912  
changed lines
  Added in v.2923

  ViewVC Help
Powered by ViewVC