/[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 384 by schoenebeck, Thu Feb 17 02:22:26 2005 UTC revision 516 by schoenebeck, Sat May 7 21:24:04 2005 UTC
# Line 25  Line 25 
25    
26  #include <iostream>  #include <iostream>
27    
28  namespace gig { namespace {  namespace gig {
29    
30    // *************** progress_t ***************
31    // *
32    
33        progress_t::progress_t() {
34            callback    = NULL;
35            custom      = NULL;
36            __range_min = 0.0f;
37            __range_max = 1.0f;
38        }
39    
40        // private helper function to convert progress of a subprocess into the global progress
41        static void __notify_progress(progress_t* pProgress, float subprogress) {
42            if (pProgress && pProgress->callback) {
43                const float totalrange    = pProgress->__range_max - pProgress->__range_min;
44                const float totalprogress = pProgress->__range_min + subprogress * totalrange;
45                pProgress->factor         = totalprogress;
46                pProgress->callback(pProgress); // now actually notify about the progress
47            }
48        }
49    
50        // private helper function to divide a progress into subprogresses
51        static void __divide_progress(progress_t* pParentProgress, progress_t* pSubProgress, float totalTasks, float currentTask) {
52            if (pParentProgress && pParentProgress->callback) {
53                const float totalrange    = pParentProgress->__range_max - pParentProgress->__range_min;
54                pSubProgress->callback    = pParentProgress->callback;
55                pSubProgress->custom      = pParentProgress->custom;
56                pSubProgress->__range_min = pParentProgress->__range_min + totalrange * currentTask / totalTasks;
57                pSubProgress->__range_max = pSubProgress->__range_min + totalrange / totalTasks;
58            }
59        }
60    
61    
62  // *************** Internal functions for sample decopmression ***************  // *************** Internal functions for sample decopmression ***************
63  // *  // *
64    
65    namespace {
66    
67      inline int get12lo(const unsigned char* pSrc)      inline int get12lo(const unsigned char* pSrc)
68      {      {
69          const int x = pSrc[0] | (pSrc[1] & 0x0f) << 8;          const int x = pSrc[0] | (pSrc[1] & 0x0f) << 8;
# Line 94  namespace gig { namespace { Line 128  namespace gig { namespace {
128      void Decompress24(int compressionmode, const unsigned char* params,      void Decompress24(int compressionmode, const unsigned char* params,
129                        int dstStep, const unsigned char* pSrc, int16_t* pDst,                        int dstStep, const unsigned char* pSrc, int16_t* pDst,
130                        unsigned long currentframeoffset,                        unsigned long currentframeoffset,
131                        unsigned long copysamples)                        unsigned long copysamples, int truncatedBits)
132      {      {
133          // Note: The 24 bits are truncated to 16 bits for now.          // Note: The 24 bits are truncated to 16 bits for now.
134    
# Line 106  namespace gig { namespace { Line 140  namespace gig { namespace {
140          //          //
141          // Strange thing #2: The formula in SKIP_ONE gives values for          // Strange thing #2: The formula in SKIP_ONE gives values for
142          // y that are twice as high as they should be. That's why          // y that are twice as high as they should be. That's why
143          // COPY_ONE shifts 9 steps instead of 8, and also why y is          // COPY_ONE shifts an extra step, and also why y is
144          // initialized with a sum instead of a mean value.          // initialized with a sum instead of a mean value.
145    
146          int y, dy, ddy;          int y, dy, ddy;
147    
148            const int shift = 8 - truncatedBits;
149            const int shift1 = shift + 1;
150    
151  #define GET_PARAMS(params)                              \  #define GET_PARAMS(params)                              \
152          y = (get24(params) + get24((params) + 3));      \          y = (get24(params) + get24((params) + 3));      \
153          dy  = get24((params) + 6);                      \          dy  = get24((params) + 6);                      \
# Line 123  namespace gig { namespace { Line 160  namespace gig { namespace {
160    
161  #define COPY_ONE(x)                             \  #define COPY_ONE(x)                             \
162          SKIP_ONE(x);                            \          SKIP_ONE(x);                            \
163          *pDst = y >> 9;                         \          *pDst = y >> shift1;                    \
164          pDst += dstStep          pDst += dstStep
165    
166          switch (compressionmode) {          switch (compressionmode) {
167              case 2: // 24 bit uncompressed              case 2: // 24 bit uncompressed
168                  pSrc += currentframeoffset * 3;                  pSrc += currentframeoffset * 3;
169                  while (copysamples) {                  while (copysamples) {
170                      *pDst = get24(pSrc) >> 8;                      *pDst = get24(pSrc) >> shift;
171                      pDst += dstStep;                      pDst += dstStep;
172                      pSrc += 3;                      pSrc += 3;
173                      copysamples--;                      copysamples--;
# Line 239  namespace gig { namespace { Line 276  namespace gig { namespace {
276    
277          if (BitDepth > 24) throw gig::Exception("Only samples up to 24 bit supported");          if (BitDepth > 24) throw gig::Exception("Only samples up to 24 bit supported");
278    
279          Compressed = (waveList->GetSubChunk(CHUNK_ID_EWAV));          RIFF::Chunk* ewav = waveList->GetSubChunk(CHUNK_ID_EWAV);
280            Compressed        = ewav;
281            Dithered          = false;
282            TruncatedBits     = 0;
283          if (Compressed) {          if (Compressed) {
284                uint32_t version = ewav->ReadInt32();
285                if (version == 3 && BitDepth == 24) {
286                    Dithered = ewav->ReadInt32();
287                    ewav->SetPos(Channels == 2 ? 84 : 64);
288                    TruncatedBits = ewav->ReadInt32();
289                }
290              ScanCompressedSample();              ScanCompressedSample();
291          }          }
292    
# Line 249  namespace gig { namespace { Line 295  namespace gig { namespace {
295              InternalDecompressionBuffer.pStart = new unsigned char[INITIAL_SAMPLE_BUFFER_SIZE];              InternalDecompressionBuffer.pStart = new unsigned char[INITIAL_SAMPLE_BUFFER_SIZE];
296              InternalDecompressionBuffer.Size   = INITIAL_SAMPLE_BUFFER_SIZE;              InternalDecompressionBuffer.Size   = INITIAL_SAMPLE_BUFFER_SIZE;
297          }          }
298          FrameOffset = 0; // just for streaming compressed samples          FrameOffset = 0; // just for streaming compressed samples
299    
300          LoopSize = LoopEnd - LoopStart;          LoopSize = LoopEnd - LoopStart;
301      }      }
# Line 846  namespace gig { namespace { Line 892  namespace gig { namespace {
892                              const unsigned char* const param_r = pSrc;                              const unsigned char* const param_r = pSrc;
893                              if (mode_r != 2) pSrc += 12;                              if (mode_r != 2) pSrc += 12;
894    
895                              Decompress24(mode_l, param_l, 2, pSrc, pDst, skipsamples, copysamples);                              Decompress24(mode_l, param_l, 2, pSrc, pDst,
896                                             skipsamples, copysamples, TruncatedBits);
897                              Decompress24(mode_r, param_r, 2, pSrc + rightChannelOffset, pDst + 1,                              Decompress24(mode_r, param_r, 2, pSrc + rightChannelOffset, pDst + 1,
898                                           skipsamples, copysamples);                                           skipsamples, copysamples, TruncatedBits);
899                              pDst += copysamples << 1;                              pDst += copysamples << 1;
900                          }                          }
901                          else { // Mono                          else { // Mono
902                              Decompress24(mode_l, param_l, 1, pSrc, pDst, skipsamples, copysamples);                              Decompress24(mode_l, param_l, 1, pSrc, pDst,
903                                             skipsamples, copysamples, TruncatedBits);
904                              pDst += copysamples;                              pDst += copysamples;
905                          }                          }
906                      }                      }
# Line 1125  namespace gig { namespace { Line 1173  namespace gig { namespace {
1173                                      VelocityResponseCurveScaling);                                      VelocityResponseCurveScaling);
1174              (*pVelocityTables)[tableKey] = pVelocityAttenuationTable; // put the new table into the tables map              (*pVelocityTables)[tableKey] = pVelocityAttenuationTable; // put the new table into the tables map
1175          }          }
1176    
1177            SampleAttenuation = pow(10.0, -Gain / (20.0 * 655360));
1178      }      }
1179    
1180      leverage_ctrl_t DimensionRegion::DecodeLeverageController(_lev_ctrl_t EncodedController) {      leverage_ctrl_t DimensionRegion::DecodeLeverageController(_lev_ctrl_t EncodedController) {
# Line 1376  namespace gig { namespace { Line 1426  namespace gig { namespace {
1426                      pDimensionDefinitions[i].zones     = 0x01 << bits; // = pow(2,bits)                      pDimensionDefinitions[i].zones     = 0x01 << bits; // = pow(2,bits)
1427                      pDimensionDefinitions[i].split_type = (dimension == dimension_layer ||                      pDimensionDefinitions[i].split_type = (dimension == dimension_layer ||
1428                                                             dimension == dimension_samplechannel ||                                                             dimension == dimension_samplechannel ||
1429                                                             dimension == dimension_releasetrigger) ? split_type_bit                                                             dimension == dimension_releasetrigger ||
1430                                                                                                    : split_type_normal;                                                             dimension == dimension_roundrobin ||
1431                                                               dimension == dimension_random) ? split_type_bit
1432                                                                                              : split_type_normal;
1433                      pDimensionDefinitions[i].ranges = NULL; // it's not possible to check velocity dimensions for custom defined ranges at this point                      pDimensionDefinitions[i].ranges = NULL; // it's not possible to check velocity dimensions for custom defined ranges at this point
1434                      pDimensionDefinitions[i].zone_size  =                      pDimensionDefinitions[i].zone_size  =
1435                          (pDimensionDefinitions[i].split_type == split_type_normal) ? 128 / pDimensionDefinitions[i].zones                          (pDimensionDefinitions[i].split_type == split_type_normal) ? 128 / pDimensionDefinitions[i].zones
# Line 1533  namespace gig { namespace { Line 1585  namespace gig { namespace {
1585          else         return static_cast<gig::Sample*>(pSample = GetSampleFromWavePool(WavePoolTableIndex));          else         return static_cast<gig::Sample*>(pSample = GetSampleFromWavePool(WavePoolTableIndex));
1586      }      }
1587    
1588      Sample* Region::GetSampleFromWavePool(unsigned int WavePoolTableIndex) {      Sample* Region::GetSampleFromWavePool(unsigned int WavePoolTableIndex, progress_t* pProgress) {
1589          if ((int32_t)WavePoolTableIndex == -1) return NULL;          if ((int32_t)WavePoolTableIndex == -1) return NULL;
1590          File* file = (File*) GetParent()->GetParent();          File* file = (File*) GetParent()->GetParent();
1591          unsigned long soughtoffset = file->pWavePoolTable[WavePoolTableIndex];          unsigned long soughtoffset = file->pWavePoolTable[WavePoolTableIndex];
1592          Sample* sample = file->GetFirstSample();          Sample* sample = file->GetFirstSample(pProgress);
1593          while (sample) {          while (sample) {
1594              if (sample->ulWavePoolOffset == soughtoffset) return static_cast<gig::Sample*>(pSample = sample);              if (sample->ulWavePoolOffset == soughtoffset) return static_cast<gig::Sample*>(pSample = sample);
1595              sample = file->GetNextSample();              sample = file->GetNextSample();
# Line 1550  namespace gig { namespace { Line 1602  namespace gig { namespace {
1602  // *************** Instrument ***************  // *************** Instrument ***************
1603  // *  // *
1604    
1605      Instrument::Instrument(File* pFile, RIFF::List* insList) : DLS::Instrument((DLS::File*)pFile, insList) {      Instrument::Instrument(File* pFile, RIFF::List* insList, progress_t* pProgress) : DLS::Instrument((DLS::File*)pFile, insList) {
1606          // Initialization          // Initialization
1607          for (int i = 0; i < 128; i++) RegionKeyTable[i] = NULL;          for (int i = 0; i < 128; i++) RegionKeyTable[i] = NULL;
1608          RegionIndex = -1;          RegionIndex = -1;
# Line 1581  namespace gig { namespace { Line 1633  namespace gig { namespace {
1633          unsigned int iRegion = 0;          unsigned int iRegion = 0;
1634          while (rgn) {          while (rgn) {
1635              if (rgn->GetListType() == LIST_TYPE_RGN) {              if (rgn->GetListType() == LIST_TYPE_RGN) {
1636                    __notify_progress(pProgress, (float) iRegion / (float) Regions);
1637                  pRegions[iRegion] = new Region(this, rgn);                  pRegions[iRegion] = new Region(this, rgn);
1638                  iRegion++;                  iRegion++;
1639              }              }
# Line 1593  namespace gig { namespace { Line 1646  namespace gig { namespace {
1646                  RegionKeyTable[iKey] = pRegions[iReg];                  RegionKeyTable[iKey] = pRegions[iReg];
1647              }              }
1648          }          }
1649    
1650            __notify_progress(pProgress, 1.0f); // notify done
1651      }      }
1652    
1653      Instrument::~Instrument() {      Instrument::~Instrument() {
# Line 1681  namespace gig { namespace { Line 1736  namespace gig { namespace {
1736          }          }
1737      }      }
1738    
1739      Sample* File::GetFirstSample() {      Sample* File::GetFirstSample(progress_t* pProgress) {
1740          if (!pSamples) LoadSamples();          if (!pSamples) LoadSamples(pProgress);
1741          if (!pSamples) return NULL;          if (!pSamples) return NULL;
1742          SamplesIterator = pSamples->begin();          SamplesIterator = pSamples->begin();
1743          return static_cast<gig::Sample*>( (SamplesIterator != pSamples->end()) ? *SamplesIterator : NULL );          return static_cast<gig::Sample*>( (SamplesIterator != pSamples->end()) ? *SamplesIterator : NULL );
# Line 1694  namespace gig { namespace { Line 1749  namespace gig { namespace {
1749          return static_cast<gig::Sample*>( (SamplesIterator != pSamples->end()) ? *SamplesIterator : NULL );          return static_cast<gig::Sample*>( (SamplesIterator != pSamples->end()) ? *SamplesIterator : NULL );
1750      }      }
1751    
1752      void File::LoadSamples() {      void File::LoadSamples(progress_t* pProgress) {
1753          RIFF::List* wvpl = pRIFF->GetSubList(LIST_TYPE_WVPL);          RIFF::List* wvpl = pRIFF->GetSubList(LIST_TYPE_WVPL);
1754          if (wvpl) {          if (wvpl) {
1755                // just for progress calculation
1756                int iSampleIndex  = 0;
1757                int iTotalSamples = wvpl->CountSubLists(LIST_TYPE_WAVE);
1758    
1759              unsigned long wvplFileOffset = wvpl->GetFilePos();              unsigned long wvplFileOffset = wvpl->GetFilePos();
1760              RIFF::List* wave = wvpl->GetFirstSubList();              RIFF::List* wave = wvpl->GetFirstSubList();
1761              while (wave) {              while (wave) {
1762                  if (wave->GetListType() == LIST_TYPE_WAVE) {                  if (wave->GetListType() == LIST_TYPE_WAVE) {
1763                        // notify current progress
1764                        const float subprogress = (float) iSampleIndex / (float) iTotalSamples;
1765                        __notify_progress(pProgress, subprogress);
1766    
1767                      if (!pSamples) pSamples = new SampleList;                      if (!pSamples) pSamples = new SampleList;
1768                      unsigned long waveFileOffset = wave->GetFilePos();                      unsigned long waveFileOffset = wave->GetFilePos();
1769                      pSamples->push_back(new Sample(this, wave, waveFileOffset - wvplFileOffset));                      pSamples->push_back(new Sample(this, wave, waveFileOffset - wvplFileOffset));
1770    
1771                        iSampleIndex++;
1772                  }                  }
1773                  wave = wvpl->GetNextSubList();                  wave = wvpl->GetNextSubList();
1774              }              }
1775                __notify_progress(pProgress, 1.0); // notify done
1776          }          }
1777          else throw gig::Exception("Mandatory <wvpl> chunk not found.");          else throw gig::Exception("Mandatory <wvpl> chunk not found.");
1778      }      }
# Line 1727  namespace gig { namespace { Line 1793  namespace gig { namespace {
1793      /**      /**
1794       * Returns the instrument with the given index.       * Returns the instrument with the given index.
1795       *       *
1796         * @param index     - number of the sought instrument (0..n)
1797         * @param pProgress - optional: callback function for progress notification
1798       * @returns  sought instrument or NULL if there's no such instrument       * @returns  sought instrument or NULL if there's no such instrument
1799       */       */
1800      Instrument* File::GetInstrument(uint index) {      Instrument* File::GetInstrument(uint index, progress_t* pProgress) {
1801          if (!pInstruments) LoadInstruments();          if (!pInstruments) {
1802                // TODO: hack - we simply load ALL samples here, it would have been done in the Region constructor anyway (ATM)
1803    
1804                // sample loading subtask
1805                progress_t subprogress;
1806                __divide_progress(pProgress, &subprogress, 3.0f, 0.0f); // randomly schedule 33% for this subtask
1807                __notify_progress(&subprogress, 0.0f);
1808                GetFirstSample(&subprogress); // now force all samples to be loaded
1809                __notify_progress(&subprogress, 1.0f);
1810    
1811                // instrument loading subtask
1812                if (pProgress && pProgress->callback) {
1813                    subprogress.__range_min = subprogress.__range_max;
1814                    subprogress.__range_max = pProgress->__range_max; // schedule remaining percentage for this subtask
1815                }
1816                __notify_progress(&subprogress, 0.0f);
1817                LoadInstruments(&subprogress);
1818                __notify_progress(&subprogress, 1.0f);
1819            }
1820          if (!pInstruments) return NULL;          if (!pInstruments) return NULL;
1821          InstrumentsIterator = pInstruments->begin();          InstrumentsIterator = pInstruments->begin();
1822          for (uint i = 0; InstrumentsIterator != pInstruments->end(); i++) {          for (uint i = 0; InstrumentsIterator != pInstruments->end(); i++) {
# Line 1740  namespace gig { namespace { Line 1826  namespace gig { namespace {
1826          return NULL;          return NULL;
1827      }      }
1828    
1829      void File::LoadInstruments() {      void File::LoadInstruments(progress_t* pProgress) {
1830          RIFF::List* lstInstruments = pRIFF->GetSubList(LIST_TYPE_LINS);          RIFF::List* lstInstruments = pRIFF->GetSubList(LIST_TYPE_LINS);
1831          if (lstInstruments) {          if (lstInstruments) {
1832                int iInstrumentIndex = 0;
1833              RIFF::List* lstInstr = lstInstruments->GetFirstSubList();              RIFF::List* lstInstr = lstInstruments->GetFirstSubList();
1834              while (lstInstr) {              while (lstInstr) {
1835                  if (lstInstr->GetListType() == LIST_TYPE_INS) {                  if (lstInstr->GetListType() == LIST_TYPE_INS) {
1836                        // notify current progress
1837                        const float localProgress = (float) iInstrumentIndex / (float) Instruments;
1838                        __notify_progress(pProgress, localProgress);
1839    
1840                        // divide local progress into subprogress for loading current Instrument
1841                        progress_t subprogress;
1842                        __divide_progress(pProgress, &subprogress, Instruments, iInstrumentIndex);
1843    
1844                      if (!pInstruments) pInstruments = new InstrumentList;                      if (!pInstruments) pInstruments = new InstrumentList;
1845                      pInstruments->push_back(new Instrument(this, lstInstr));                      pInstruments->push_back(new Instrument(this, lstInstr, &subprogress));
1846    
1847                        iInstrumentIndex++;
1848                  }                  }
1849                  lstInstr = lstInstruments->GetNextSubList();                  lstInstr = lstInstruments->GetNextSubList();
1850              }              }
1851                __notify_progress(pProgress, 1.0); // notify done
1852          }          }
1853          else throw gig::Exception("Mandatory <lins> list chunk not found.");          else throw gig::Exception("Mandatory <lins> list chunk not found.");
1854      }      }

Legend:
Removed from v.384  
changed lines
  Added in v.516

  ViewVC Help
Powered by ViewVC