/[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 1627 by persson, Sun Jan 6 10:53:53 2008 UTC revision 2394 by schoenebeck, Mon Jan 7 23:23:58 2013 UTC
# Line 2  Line 2 
2   *                                                                         *   *                                                                         *
3   *   libgig - C++ cross-platform Gigasampler format file access library    *   *   libgig - C++ cross-platform Gigasampler format file access library    *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003-2007 by Christian Schoenebeck                      *   *   Copyright (C) 2003-2013 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 25  Line 25 
25    
26  #include "helper.h"  #include "helper.h"
27    
28    #include <algorithm>
29  #include <math.h>  #include <math.h>
30  #include <iostream>  #include <iostream>
31    
# Line 676  namespace { Line 677  namespace {
677          if (SampleCount > this->SamplesTotal) SampleCount = this->SamplesTotal;          if (SampleCount > this->SamplesTotal) SampleCount = this->SamplesTotal;
678          if (RAMCache.pStart) delete[] (int8_t*) RAMCache.pStart;          if (RAMCache.pStart) delete[] (int8_t*) RAMCache.pStart;
679          unsigned long allocationsize = (SampleCount + NullSamplesCount) * this->FrameSize;          unsigned long allocationsize = (SampleCount + NullSamplesCount) * this->FrameSize;
680            SetPos(0); // reset read position to begin of sample
681          RAMCache.pStart            = new int8_t[allocationsize];          RAMCache.pStart            = new int8_t[allocationsize];
682          RAMCache.Size              = Read(RAMCache.pStart, SampleCount) * this->FrameSize;          RAMCache.Size              = Read(RAMCache.pStart, SampleCount) * this->FrameSize;
683          RAMCache.NullExtensionSize = allocationsize - RAMCache.Size;          RAMCache.NullExtensionSize = allocationsize - RAMCache.Size;
# Line 713  namespace { Line 715  namespace {
715          if (RAMCache.pStart) delete[] (int8_t*) RAMCache.pStart;          if (RAMCache.pStart) delete[] (int8_t*) RAMCache.pStart;
716          RAMCache.pStart = NULL;          RAMCache.pStart = NULL;
717          RAMCache.Size   = 0;          RAMCache.Size   = 0;
718            RAMCache.NullExtensionSize = 0;
719      }      }
720    
721      /** @brief Resize sample.      /** @brief Resize sample.
# Line 907  namespace { Line 910  namespace {
910                                  }                                  }
911    
912                                  // reverse the sample frames for backward playback                                  // reverse the sample frames for backward playback
913                                  SwapMemoryArea(&pDst[swapareastart * this->FrameSize], (totalreadsamples - swapareastart) * this->FrameSize, this->FrameSize);                                  if (totalreadsamples > swapareastart) //FIXME: this if() is just a crash workaround for now (#102), but totalreadsamples <= swapareastart should never be the case, so there's probably still a bug above!
914                                        SwapMemoryArea(&pDst[swapareastart * this->FrameSize], (totalreadsamples - swapareastart) * this->FrameSize, this->FrameSize);
915                              }                              }
916                          } while (samplestoread && readsamples);                          } while (samplestoread && readsamples);
917                          break;                          break;
# Line 1577  namespace { Line 1581  namespace {
1581       */       */
1582      DimensionRegion::DimensionRegion(RIFF::List* _3ewl, const DimensionRegion& src) : DLS::Sampler(_3ewl) {      DimensionRegion::DimensionRegion(RIFF::List* _3ewl, const DimensionRegion& src) : DLS::Sampler(_3ewl) {
1583          Instances++;          Instances++;
1584            //NOTE: I think we cannot call CopyAssign() here (in a constructor) as long as its a virtual method
1585          *this = src; // default memberwise shallow copy of all parameters          *this = src; // default memberwise shallow copy of all parameters
1586          pParentList = _3ewl; // restore the chunk pointer          pParentList = _3ewl; // restore the chunk pointer
1587    
# Line 1592  namespace { Line 1597  namespace {
1597                  pSampleLoops[k] = src.pSampleLoops[k];                  pSampleLoops[k] = src.pSampleLoops[k];
1598          }          }
1599      }      }
1600        
1601        /**
1602         * Make a (semi) deep copy of the DimensionRegion object given by @a orig
1603         * and assign it to this object.
1604         *
1605         * Note that all sample pointers referenced by @a orig are simply copied as
1606         * memory address. Thus the respective samples are shared, not duplicated!
1607         *
1608         * @param orig - original DimensionRegion object to be copied from
1609         */
1610        void DimensionRegion::CopyAssign(const DimensionRegion* orig) {
1611            // delete all allocated data first
1612            if (VelocityTable) delete [] VelocityTable;
1613            if (pSampleLoops) delete [] pSampleLoops;
1614            
1615            // backup parent list pointer
1616            RIFF::List* p = pParentList;
1617            
1618            //NOTE: copy code copied from assignment constructor above, see comment there as well
1619            
1620            *this = *orig; // default memberwise shallow copy of all parameters
1621            pParentList = p; // restore the chunk pointer
1622    
1623            // deep copy of owned structures
1624            if (orig->VelocityTable) {
1625                VelocityTable = new uint8_t[128];
1626                for (int k = 0 ; k < 128 ; k++)
1627                    VelocityTable[k] = orig->VelocityTable[k];
1628            }
1629            if (orig->pSampleLoops) {
1630                pSampleLoops = new DLS::sample_loop_t[orig->SampleLoops];
1631                for (int k = 0 ; k < orig->SampleLoops ; k++)
1632                    pSampleLoops[k] = orig->pSampleLoops[k];
1633            }
1634        }
1635    
1636      /**      /**
1637       * Updates the respective member variable and updates @c SampleAttenuation       * Updates the respective member variable and updates @c SampleAttenuation
# Line 1834  namespace { Line 1874  namespace {
1874    
1875          const uint16_t eg3depth = (EG3Depth >= 0) ? EG3Depth          const uint16_t eg3depth = (EG3Depth >= 0) ? EG3Depth
1876                                                    : uint16_t(((-EG3Depth) - 1) ^ 0xffff); /* binary complementary for negatives */                                                    : uint16_t(((-EG3Depth) - 1) ^ 0xffff); /* binary complementary for negatives */
1877          pData[116] = eg3depth;          store16(&pData[116], eg3depth);
1878    
1879          // next 2 bytes unknown          // next 2 bytes unknown
1880    
# Line 1881  namespace { Line 1921  namespace {
1921                                        (VCFKeyboardTrackingBreakpoint & 0x7f); /* lower 7 bits */                                        (VCFKeyboardTrackingBreakpoint & 0x7f); /* lower 7 bits */
1922          pData[137] = vcfbreakpoint;          pData[137] = vcfbreakpoint;
1923    
1924          const uint8_t vcfvelocity = VCFVelocityDynamicRange % 5 |          const uint8_t vcfvelocity = VCFVelocityDynamicRange % 5 +
1925                                      VCFVelocityCurve * 5;                                      VCFVelocityCurve * 5;
1926          pData[138] = vcfvelocity;          pData[138] = vcfvelocity;
1927    
# Line 2921  namespace { Line 2961  namespace {
2961          }          }
2962          return NULL;          return NULL;
2963      }      }
2964        
2965        /**
2966         * Make a (semi) deep copy of the Region object given by @a orig
2967         * and assign it to this object.
2968         *
2969         * Note that all sample pointers referenced by @a orig are simply copied as
2970         * memory address. Thus the respective samples are shared, not duplicated!
2971         *
2972         * @param orig - original Region object to be copied from
2973         */
2974        void Region::CopyAssign(const Region* orig) {
2975            // handle base classes
2976            DLS::Region::CopyAssign(orig);
2977            
2978            // handle own member variables
2979            for (int i = Dimensions - 1; i >= 0; --i) {
2980                DeleteDimension(&pDimensionDefinitions[i]);
2981            }
2982            Layers = 0; // just to be sure
2983            for (int i = 0; i < orig->Dimensions; i++) {
2984                // we need to copy the dim definition here, to avoid the compiler
2985                // complaining about const-ness issue
2986                dimension_def_t def = orig->pDimensionDefinitions[i];
2987                AddDimension(&def);
2988            }
2989            for (int i = 0; i < 256; i++) {
2990                if (pDimensionRegions[i] && orig->pDimensionRegions[i]) {
2991                    pDimensionRegions[i]->CopyAssign(
2992                        orig->pDimensionRegions[i]
2993                    );
2994                }
2995            }
2996            Layers = orig->Layers;
2997        }
2998    
2999    
3000  // *************** MidiRule ***************  // *************** MidiRule ***************
# Line 2965  MidiRuleCtrlTrigger::MidiRuleCtrlTrigger Line 3039  MidiRuleCtrlTrigger::MidiRuleCtrlTrigger
3039          PianoReleaseMode = false;          PianoReleaseMode = false;
3040          DimensionKeyRange.low = 0;          DimensionKeyRange.low = 0;
3041          DimensionKeyRange.high = 0;          DimensionKeyRange.high = 0;
3042            pMidiRules = new MidiRule*[3];
3043            pMidiRules[0] = NULL;
3044    
3045          // Loading          // Loading
3046          RIFF::List* lart = insList->GetSubList(LIST_TYPE_LART);          RIFF::List* lart = insList->GetSubList(LIST_TYPE_LART);
# Line 2982  MidiRuleCtrlTrigger::MidiRuleCtrlTrigger Line 3058  MidiRuleCtrlTrigger::MidiRuleCtrlTrigger
3058    
3059                  if (_3ewg->GetSize() > 32) {                  if (_3ewg->GetSize() > 32) {
3060                      // read MIDI rules                      // read MIDI rules
3061                        int i = 0;
3062                      _3ewg->SetPos(32);                      _3ewg->SetPos(32);
3063                      uint8_t id1 = _3ewg->ReadUint8();                      uint8_t id1 = _3ewg->ReadUint8();
3064                      uint8_t id2 = _3ewg->ReadUint8();                      uint8_t id2 = _3ewg->ReadUint8();
3065    
3066                      if (id1 == 4 && id2 == 16) {                      if (id1 == 4 && id2 == 16) {
3067                          MidiRules.push_back(new MidiRuleCtrlTrigger(_3ewg));                          pMidiRules[i++] = new MidiRuleCtrlTrigger(_3ewg);
3068                      }                      }
3069                      //TODO: all the other types of rules                      //TODO: all the other types of rules
3070    
3071                        pMidiRules[i] = NULL;
3072                  }                  }
3073              }              }
3074          }          }
# Line 3027  MidiRuleCtrlTrigger::MidiRuleCtrlTrigger Line 3106  MidiRuleCtrlTrigger::MidiRuleCtrlTrigger
3106      }      }
3107    
3108      Instrument::~Instrument() {      Instrument::~Instrument() {
3109            for (int i = 0 ; pMidiRules[i] ; i++) {
3110                delete pMidiRules[i];
3111            }
3112            delete[] pMidiRules;
3113      }      }
3114    
3115      /**      /**
# Line 3142  MidiRuleCtrlTrigger::MidiRuleCtrlTrigger Line 3225  MidiRuleCtrlTrigger::MidiRuleCtrlTrigger
3225      }      }
3226    
3227      /**      /**
3228       * Returns the first MIDI rule of the instrument. You have to call       * Returns a MIDI rule of the instrument.
      * this method once before you use GetNextMidiRule().  
3229       *       *
3230       * The list of MIDI rules, at least in gig v3, always contains at       * The list of MIDI rules, at least in gig v3, always contains at
3231       * most two rules. The second rule can only be the DEF filter       * most two rules. The second rule can only be the DEF filter
3232       * (which currently isn't supported by libgig).       * (which currently isn't supported by libgig).
3233       *       *
3234       * @returns  pointer address to first MIDI rule or NULL if there is none       * @param i - MIDI rule number
3235       * @see      GetNextMidiRule()       * @returns   pointer address to MIDI rule number i or NULL if there is none
3236       */       */
3237      MidiRule* Instrument::GetFirstMidiRule() {      MidiRule* Instrument::GetMidiRule(int i) {
3238          MidiRulesIterator = MidiRules.begin();          return pMidiRules[i];
         return MidiRulesIterator != MidiRules.end() ? *MidiRulesIterator : NULL;  
3239      }      }
3240        
3241      /**      /**
3242       * Returns the next MIDI rule of the instrument. You have to call       * Make a (semi) deep copy of the Instrument object given by @a orig
3243       * GetFirstMidiRule() once before you can use this method. By       * and assign it to this object.
3244       * calling this method multiple times it iterates through the       *
3245       * available rules.       * Note that all sample pointers referenced by @a orig are simply copied as
3246       *       * memory address. Thus the respective samples are shared, not duplicated!
3247       * @returns  pointer address to the next MIDI rule or NULL if end reached       *
3248       * @see      GetFirstMidiRule()       * @param orig - original Instrument object to be copied from
3249       */       */
3250      MidiRule* Instrument::GetNextMidiRule() {      void Instrument::CopyAssign(const Instrument* orig) {
3251          MidiRulesIterator++;          // handle base class
3252          return MidiRulesIterator != MidiRules.end() ? *MidiRulesIterator : NULL;          // (without copying DLS region stuff)
3253            DLS::Instrument::CopyAssignCore(orig);
3254            
3255            // handle own member variables
3256            Attenuation = orig->Attenuation;
3257            EffectSend = orig->EffectSend;
3258            FineTune = orig->FineTune;
3259            PitchbendRange = orig->PitchbendRange;
3260            PianoReleaseMode = orig->PianoReleaseMode;
3261            DimensionKeyRange = orig->DimensionKeyRange;
3262            
3263            // free old midi rules
3264            for (int i = 0 ; pMidiRules[i] ; i++) {
3265                delete pMidiRules[i];
3266            }
3267            //TODO: MIDI rule copying
3268            pMidiRules[0] = NULL;
3269            
3270            // delete all old regions
3271            while (Regions) DeleteRegion(GetFirstRegion());
3272            // create new regions and copy them from original
3273            {
3274                RegionList::const_iterator it = orig->pRegions->begin();
3275                for (int i = 0; i < orig->Regions; ++i, ++it) {
3276                    Region* dstRgn = AddRegion();
3277                    //NOTE: Region does semi-deep copy !
3278                    dstRgn->CopyAssign(
3279                        static_cast<gig::Region*>(*it)
3280                    );
3281                }
3282            }
3283    
3284            UpdateRegionKeyTable();
3285      }      }
3286    
3287    
# Line 3413  MidiRuleCtrlTrigger::MidiRuleCtrlTrigger Line 3526  MidiRuleCtrlTrigger::MidiRuleCtrlTrigger
3526          pSamples->erase(iter);          pSamples->erase(iter);
3527          delete pSample;          delete pSample;
3528    
3529            SampleList::iterator tmp = SamplesIterator;
3530          // remove all references to the sample          // remove all references to the sample
3531          for (Instrument* instrument = GetFirstInstrument() ; instrument ;          for (Instrument* instrument = GetFirstInstrument() ; instrument ;
3532               instrument = GetNextInstrument()) {               instrument = GetNextInstrument()) {
# Line 3427  MidiRuleCtrlTrigger::MidiRuleCtrlTrigger Line 3541  MidiRuleCtrlTrigger::MidiRuleCtrlTrigger
3541                  }                  }
3542              }              }
3543          }          }
3544            SamplesIterator = tmp; // restore iterator
3545      }      }
3546    
3547      void File::LoadSamples() {      void File::LoadSamples() {
# Line 3567  MidiRuleCtrlTrigger::MidiRuleCtrlTrigger Line 3682  MidiRuleCtrlTrigger::MidiRuleCtrlTrigger
3682         pInstruments->push_back(pInstrument);         pInstruments->push_back(pInstrument);
3683         return pInstrument;         return pInstrument;
3684      }      }
3685        
3686        /** @brief Add a duplicate of an existing instrument.
3687         *
3688         * Duplicates the instrument definition given by @a orig and adds it
3689         * to this file. This allows in an instrument editor application to
3690         * easily create variations of an instrument, which will be stored in
3691         * the same .gig file, sharing i.e. the same samples.
3692         *
3693         * Note that all sample pointers referenced by @a orig are simply copied as
3694         * memory address. Thus the respective samples are shared, not duplicated!
3695         *
3696         * You have to call Save() to make this persistent to the file.
3697         *
3698         * @param orig - original instrument to be copied
3699         * @returns duplicated copy of the given instrument
3700         */
3701        Instrument* File::AddDuplicateInstrument(const Instrument* orig) {
3702            Instrument* instr = AddInstrument();
3703            instr->CopyAssign(orig);
3704            return instr;
3705        }
3706    
3707      /** @brief Delete an instrument.      /** @brief Delete an instrument.
3708       *       *

Legend:
Removed from v.1627  
changed lines
  Added in v.2394

  ViewVC Help
Powered by ViewVC