/[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 1358 by schoenebeck, Sun Sep 30 18:13:33 2007 UTC revision 1678 by persson, Sun Feb 10 16:07:22 2008 UTC
# Line 255  namespace { Line 255  namespace {
255    
256    
257    
258    // *************** Internal CRC-32 (Cyclic Redundancy Check) functions  ***************
259    // *
260    
261        static uint32_t* __initCRCTable() {
262            static uint32_t res[256];
263    
264            for (int i = 0 ; i < 256 ; i++) {
265                uint32_t c = i;
266                for (int j = 0 ; j < 8 ; j++) {
267                    c = (c & 1) ? 0xedb88320 ^ (c >> 1) : c >> 1;
268                }
269                res[i] = c;
270            }
271            return res;
272        }
273    
274        static const uint32_t* __CRCTable = __initCRCTable();
275    
276        /**
277         * Initialize a CRC variable.
278         *
279         * @param crc - variable to be initialized
280         */
281        inline static void __resetCRC(uint32_t& crc) {
282            crc = 0xffffffff;
283        }
284    
285        /**
286         * Used to calculate checksums of the sample data in a gig file. The
287         * checksums are stored in the 3crc chunk of the gig file and
288         * automatically updated when a sample is written with Sample::Write().
289         *
290         * One should call __resetCRC() to initialize the CRC variable to be
291         * used before calling this function the first time.
292         *
293         * After initializing the CRC variable one can call this function
294         * arbitrary times, i.e. to split the overall CRC calculation into
295         * steps.
296         *
297         * Once the whole data was processed by __calculateCRC(), one should
298         * call __encodeCRC() to get the final CRC result.
299         *
300         * @param buf     - pointer to data the CRC shall be calculated of
301         * @param bufSize - size of the data to be processed
302         * @param crc     - variable the CRC sum shall be stored to
303         */
304        static void __calculateCRC(unsigned char* buf, int bufSize, uint32_t& crc) {
305            for (int i = 0 ; i < bufSize ; i++) {
306                crc = __CRCTable[(crc ^ buf[i]) & 0xff] ^ (crc >> 8);
307            }
308        }
309    
310        /**
311         * Returns the final CRC result.
312         *
313         * @param crc - variable previously passed to __calculateCRC()
314         */
315        inline static uint32_t __encodeCRC(const uint32_t& crc) {
316            return crc ^ 0xffffffff;
317        }
318    
319    
320    
321  // *************** Other Internal functions  ***************  // *************** Other Internal functions  ***************
322  // *  // *
323    
# Line 278  namespace { Line 341  namespace {
341    
342    
343    
 // *************** CRC ***************  
 // *  
   
     const uint32_t* CRC::table(initTable());  
   
     uint32_t* CRC::initTable() {  
         uint32_t* res = new uint32_t[256];  
   
         for (int i = 0 ; i < 256 ; i++) {  
             uint32_t c = i;  
             for (int j = 0 ; j < 8 ; j++) {  
                 c = (c & 1) ? 0xedb88320 ^ (c >> 1) : c >> 1;  
             }  
             res[i] = c;  
         }  
         return res;  
     }  
   
   
   
344  // *************** Sample ***************  // *************** Sample ***************
345  // *  // *
346    
# Line 323  namespace { Line 366  namespace {
366       *                         is located, 0 otherwise       *                         is located, 0 otherwise
367       */       */
368      Sample::Sample(File* pFile, RIFF::List* waveList, unsigned long WavePoolOffset, unsigned long fileNo) : DLS::Sample((DLS::File*) pFile, waveList, WavePoolOffset) {      Sample::Sample(File* pFile, RIFF::List* waveList, unsigned long WavePoolOffset, unsigned long fileNo) : DLS::Sample((DLS::File*) pFile, waveList, WavePoolOffset) {
369          static const DLS::Info::FixedStringLength fixedStringLengths[] = {          static const DLS::Info::string_length_t fixedStringLengths[] = {
370              { CHUNK_ID_INAM, 64 },              { CHUNK_ID_INAM, 64 },
371              { 0, 0 }              { 0, 0 }
372          };          };
373          pInfo->FixedStringLengths = fixedStringLengths;          pInfo->SetFixedStringLengths(fixedStringLengths);
374          Instances++;          Instances++;
375          FileNo = fileNo;          FileNo = fileNo;
376    
377            __resetCRC(crc);
378    
379          pCk3gix = waveList->GetSubChunk(CHUNK_ID_3GIX);          pCk3gix = waveList->GetSubChunk(CHUNK_ID_3GIX);
380          if (pCk3gix) {          if (pCk3gix) {
381              uint16_t iSampleGroup = pCk3gix->ReadInt16();              uint16_t iSampleGroup = pCk3gix->ReadInt16();
# Line 1168  namespace { Line 1213  namespace {
1213          // if this is the first write in this sample, reset the          // if this is the first write in this sample, reset the
1214          // checksum calculator          // checksum calculator
1215          if (pCkData->GetPos() == 0) {          if (pCkData->GetPos() == 0) {
1216              crc.reset();              __resetCRC(crc);
1217          }          }
1218          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");
1219          unsigned long res;          unsigned long res;
# Line 1178  namespace { Line 1223  namespace {
1223              res = Channels == 2 ? pCkData->Write(pBuffer, SampleCount << 1, 2) >> 1              res = Channels == 2 ? pCkData->Write(pBuffer, SampleCount << 1, 2) >> 1
1224                                  : pCkData->Write(pBuffer, SampleCount, 2);                                  : pCkData->Write(pBuffer, SampleCount, 2);
1225          }          }
1226          crc.update((unsigned char *)pBuffer, SampleCount * FrameSize);          __calculateCRC((unsigned char *)pBuffer, SampleCount * FrameSize, crc);
1227    
1228          // if this is the last write, update the checksum chunk in the          // if this is the last write, update the checksum chunk in the
1229          // file          // file
1230          if (pCkData->GetPos() == pCkData->GetSize()) {          if (pCkData->GetPos() == pCkData->GetSize()) {
1231              File* pFile = static_cast<File*>(GetParent());              File* pFile = static_cast<File*>(GetParent());
1232              pFile->SetSampleChecksum(this, crc.getValue());              pFile->SetSampleChecksum(this, __encodeCRC(crc));
1233          }          }
1234          return res;          return res;
1235      }      }
# Line 2327  namespace { Line 2372  namespace {
2372    
2373          // Actual Loading          // Actual Loading
2374    
2375            if (!file->GetAutoLoad()) return;
2376    
2377          LoadDimensionRegions(rgnList);          LoadDimensionRegions(rgnList);
2378    
2379          RIFF::Chunk* _3lnk = rgnList->GetSubChunk(CHUNK_ID_3LNK);          RIFF::Chunk* _3lnk = rgnList->GetSubChunk(CHUNK_ID_3LNK);
# Line 2370  namespace { Line 2417  namespace {
2417              else              else
2418                  _3lnk->SetPos(44);                  _3lnk->SetPos(44);
2419    
2420              // load sample references              // load sample references (if auto loading is enabled)
2421              for (uint i = 0; i < DimensionRegions; i++) {              if (file->GetAutoLoad()) {
2422                  uint32_t wavepoolindex = _3lnk->ReadUint32();                  for (uint i = 0; i < DimensionRegions; i++) {
2423                  if (file->pWavePoolTable) pDimensionRegions[i]->pSample = GetSampleFromWavePool(wavepoolindex);                      uint32_t wavepoolindex = _3lnk->ReadUint32();
2424                        if (file->pWavePoolTable) pDimensionRegions[i]->pSample = GetSampleFromWavePool(wavepoolindex);
2425                    }
2426                    GetSample(); // load global region sample reference
2427              }              }
             GetSample(); // load global region sample reference  
2428          } else {          } else {
2429              DimensionRegions = 0;              DimensionRegions = 0;
2430              for (int i = 0 ; i < 8 ; i++) {              for (int i = 0 ; i < 8 ; i++) {
# Line 2874  namespace { Line 2923  namespace {
2923      }      }
2924    
2925    
2926    // *************** MidiRule ***************
2927    // *
2928    
2929    MidiRuleCtrlTrigger::MidiRuleCtrlTrigger(RIFF::Chunk* _3ewg) {
2930        _3ewg->SetPos(36);
2931        Triggers = _3ewg->ReadUint8();
2932        _3ewg->SetPos(40);
2933        ControllerNumber = _3ewg->ReadUint8();
2934        _3ewg->SetPos(46);
2935        for (int i = 0 ; i < Triggers ; i++) {
2936            pTriggers[i].TriggerPoint = _3ewg->ReadUint8();
2937            pTriggers[i].Descending = _3ewg->ReadUint8();
2938            pTriggers[i].VelSensitivity = _3ewg->ReadUint8();
2939            pTriggers[i].Key = _3ewg->ReadUint8();
2940            pTriggers[i].NoteOff = _3ewg->ReadUint8();
2941            pTriggers[i].Velocity = _3ewg->ReadUint8();
2942            pTriggers[i].OverridePedal = _3ewg->ReadUint8();
2943            _3ewg->ReadUint8();
2944        }
2945    }
2946    
2947    
2948  // *************** Instrument ***************  // *************** Instrument ***************
2949  // *  // *
2950    
2951      Instrument::Instrument(File* pFile, RIFF::List* insList, progress_t* pProgress) : DLS::Instrument((DLS::File*)pFile, insList) {      Instrument::Instrument(File* pFile, RIFF::List* insList, progress_t* pProgress) : DLS::Instrument((DLS::File*)pFile, insList) {
2952          static const DLS::Info::FixedStringLength fixedStringLengths[] = {          static const DLS::Info::string_length_t fixedStringLengths[] = {
2953              { CHUNK_ID_INAM, 64 },              { CHUNK_ID_INAM, 64 },
2954              { CHUNK_ID_ISFT, 12 },              { CHUNK_ID_ISFT, 12 },
2955              { 0, 0 }              { 0, 0 }
2956          };          };
2957          pInfo->FixedStringLengths = fixedStringLengths;          pInfo->SetFixedStringLengths(fixedStringLengths);
2958    
2959          // Initialization          // Initialization
2960          for (int i = 0; i < 128; i++) RegionKeyTable[i] = NULL;          for (int i = 0; i < 128; i++) RegionKeyTable[i] = NULL;
# Line 2895  namespace { Line 2965  namespace {
2965          PianoReleaseMode = false;          PianoReleaseMode = false;
2966          DimensionKeyRange.low = 0;          DimensionKeyRange.low = 0;
2967          DimensionKeyRange.high = 0;          DimensionKeyRange.high = 0;
2968            pMidiRules = new MidiRule*[3];
2969            pMidiRules[0] = NULL;
2970    
2971          // Loading          // Loading
2972          RIFF::List* lart = insList->GetSubList(LIST_TYPE_LART);          RIFF::List* lart = insList->GetSubList(LIST_TYPE_LART);
# Line 2909  namespace { Line 2981  namespace {
2981                  PianoReleaseMode       = dimkeystart & 0x01;                  PianoReleaseMode       = dimkeystart & 0x01;
2982                  DimensionKeyRange.low  = dimkeystart >> 1;                  DimensionKeyRange.low  = dimkeystart >> 1;
2983                  DimensionKeyRange.high = _3ewg->ReadUint8();                  DimensionKeyRange.high = _3ewg->ReadUint8();
2984    
2985                    if (_3ewg->GetSize() > 32) {
2986                        // read MIDI rules
2987                        int i = 0;
2988                        _3ewg->SetPos(32);
2989                        uint8_t id1 = _3ewg->ReadUint8();
2990                        uint8_t id2 = _3ewg->ReadUint8();
2991    
2992                        if (id1 == 4 && id2 == 16) {
2993                            pMidiRules[i++] = new MidiRuleCtrlTrigger(_3ewg);
2994                        }
2995                        //TODO: all the other types of rules
2996    
2997                        pMidiRules[i] = NULL;
2998                    }
2999              }              }
3000          }          }
3001    
3002          if (!pRegions) pRegions = new RegionList;          if (pFile->GetAutoLoad()) {
3003          RIFF::List* lrgn = insList->GetSubList(LIST_TYPE_LRGN);              if (!pRegions) pRegions = new RegionList;
3004          if (lrgn) {              RIFF::List* lrgn = insList->GetSubList(LIST_TYPE_LRGN);
3005              RIFF::List* rgn = lrgn->GetFirstSubList();              if (lrgn) {
3006              while (rgn) {                  RIFF::List* rgn = lrgn->GetFirstSubList();
3007                  if (rgn->GetListType() == LIST_TYPE_RGN) {                  while (rgn) {
3008                      __notify_progress(pProgress, (float) pRegions->size() / (float) Regions);                      if (rgn->GetListType() == LIST_TYPE_RGN) {
3009                      pRegions->push_back(new Region(this, rgn));                          __notify_progress(pProgress, (float) pRegions->size() / (float) Regions);
3010                            pRegions->push_back(new Region(this, rgn));
3011                        }
3012                        rgn = lrgn->GetNextSubList();
3013                  }                  }
3014                  rgn = lrgn->GetNextSubList();                  // Creating Region Key Table for fast lookup
3015                    UpdateRegionKeyTable();
3016              }              }
             // Creating Region Key Table for fast lookup  
             UpdateRegionKeyTable();  
3017          }          }
3018    
3019          __notify_progress(pProgress, 1.0f); // notify done          __notify_progress(pProgress, 1.0f); // notify done
# Line 2943  namespace { Line 3032  namespace {
3032      }      }
3033    
3034      Instrument::~Instrument() {      Instrument::~Instrument() {
3035            delete[] pMidiRules;
3036      }      }
3037    
3038      /**      /**
# Line 3057  namespace { Line 3147  namespace {
3147          UpdateRegionKeyTable();          UpdateRegionKeyTable();
3148      }      }
3149    
3150        /**
3151         * Returns a MIDI rule of the instrument.
3152         *
3153         * The list of MIDI rules, at least in gig v3, always contains at
3154         * most two rules. The second rule can only be the DEF filter
3155         * (which currently isn't supported by libgig).
3156         *
3157         * @param i - MIDI rule number
3158         * @returns   pointer address to MIDI rule number i or NULL if there is none
3159         */
3160        MidiRule* Instrument::GetMidiRule(int i) {
3161            return pMidiRules[i];
3162        }
3163    
3164    
3165  // *************** Group ***************  // *************** Group ***************
# Line 3182  namespace { Line 3285  namespace {
3285  // *************** File ***************  // *************** File ***************
3286  // *  // *
3287    
3288      // File version 2.0, 1998-06-28      /// Reflects Gigasampler file format version 2.0 (1998-06-28).
3289      const DLS::version_t File::VERSION_2 = {      const DLS::version_t File::VERSION_2 = {
3290          0, 2, 19980628 & 0xffff, 19980628 >> 16          0, 2, 19980628 & 0xffff, 19980628 >> 16
3291      };      };
3292    
3293      // File version 3.0, 2003-03-31      /// Reflects Gigasampler file format version 3.0 (2003-03-31).
3294      const DLS::version_t File::VERSION_3 = {      const DLS::version_t File::VERSION_3 = {
3295          0, 3, 20030331 & 0xffff, 20030331 >> 16          0, 3, 20030331 & 0xffff, 20030331 >> 16
3296      };      };
3297    
3298      const DLS::Info::FixedStringLength File::FixedStringLengths[] = {      static const DLS::Info::string_length_t _FileFixedStringLengths[] = {
3299          { CHUNK_ID_IARL, 256 },          { CHUNK_ID_IARL, 256 },
3300          { CHUNK_ID_IART, 128 },          { CHUNK_ID_IART, 128 },
3301          { CHUNK_ID_ICMS, 128 },          { CHUNK_ID_ICMS, 128 },
# Line 3214  namespace { Line 3317  namespace {
3317      };      };
3318    
3319      File::File() : DLS::File() {      File::File() : DLS::File() {
3320            bAutoLoad = true;
3321          *pVersion = VERSION_3;          *pVersion = VERSION_3;
3322          pGroups = NULL;          pGroups = NULL;
3323          pInfo->FixedStringLengths = FixedStringLengths;          pInfo->SetFixedStringLengths(_FileFixedStringLengths);
3324          pInfo->ArchivalLocation = String(256, ' ');          pInfo->ArchivalLocation = String(256, ' ');
3325    
3326          // add some mandatory chunks to get the file chunks in right          // add some mandatory chunks to get the file chunks in right
# Line 3229  namespace { Line 3333  namespace {
3333      }      }
3334    
3335      File::File(RIFF::File* pRIFF) : DLS::File(pRIFF) {      File::File(RIFF::File* pRIFF) : DLS::File(pRIFF) {
3336            bAutoLoad = true;
3337          pGroups = NULL;          pGroups = NULL;
3338          pInfo->FixedStringLengths = FixedStringLengths;          pInfo->SetFixedStringLengths(_FileFixedStringLengths);
3339      }      }
3340    
3341      File::~File() {      File::~File() {
# Line 3298  namespace { Line 3403  namespace {
3403          pSamples->erase(iter);          pSamples->erase(iter);
3404          delete pSample;          delete pSample;
3405    
3406            SampleList::iterator tmp = SamplesIterator;
3407          // remove all references to the sample          // remove all references to the sample
3408          for (Instrument* instrument = GetFirstInstrument() ; instrument ;          for (Instrument* instrument = GetFirstInstrument() ; instrument ;
3409               instrument = GetNextInstrument()) {               instrument = GetNextInstrument()) {
# Line 3312  namespace { Line 3418  namespace {
3418                  }                  }
3419              }              }
3420          }          }
3421            SamplesIterator = tmp; // restore iterator
3422      }      }
3423    
3424      void File::LoadSamples() {      void File::LoadSamples() {
# Line 3402  namespace { Line 3509  namespace {
3509              progress_t subprogress;              progress_t subprogress;
3510              __divide_progress(pProgress, &subprogress, 3.0f, 0.0f); // randomly schedule 33% for this subtask              __divide_progress(pProgress, &subprogress, 3.0f, 0.0f); // randomly schedule 33% for this subtask
3511              __notify_progress(&subprogress, 0.0f);              __notify_progress(&subprogress, 0.0f);
3512              GetFirstSample(&subprogress); // now force all samples to be loaded              if (GetAutoLoad())
3513                    GetFirstSample(&subprogress); // now force all samples to be loaded
3514              __notify_progress(&subprogress, 1.0f);              __notify_progress(&subprogress, 1.0f);
3515    
3516              // instrument loading subtask              // instrument loading subtask
# Line 3809  namespace { Line 3917  namespace {
3917          }          }
3918      }      }
3919    
3920        /**
3921         * Enable / disable automatic loading. By default this properyt is
3922         * enabled and all informations are loaded automatically. However
3923         * loading all Regions, DimensionRegions and especially samples might
3924         * take a long time for large .gig files, and sometimes one might only
3925         * be interested in retrieving very superficial informations like the
3926         * amount of instruments and their names. In this case one might disable
3927         * automatic loading to avoid very slow response times.
3928         *
3929         * @e CAUTION: by disabling this property many pointers (i.e. sample
3930         * references) and informations will have invalid or even undefined
3931         * data! This feature is currently only intended for retrieving very
3932         * superficial informations in a very fast way. Don't use it to retrieve
3933         * details like synthesis informations or even to modify .gig files!
3934         */
3935        void File::SetAutoLoad(bool b) {
3936            bAutoLoad = b;
3937        }
3938    
3939        /**
3940         * Returns whether automatic loading is enabled.
3941         * @see SetAutoLoad()
3942         */
3943        bool File::GetAutoLoad() {
3944            return bAutoLoad;
3945        }
3946    
3947    
3948    
3949  // *************** Exception ***************  // *************** Exception ***************

Legend:
Removed from v.1358  
changed lines
  Added in v.1678

  ViewVC Help
Powered by ViewVC