/[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 2609 by schoenebeck, Sun Jun 8 19:00:30 2014 UTC revision 2909 by schoenebeck, Thu May 12 19:34:17 2016 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-2013 by Christian Schoenebeck                      *   *   Copyright (C) 2003-2014 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 144  namespace DLS { Line 144  namespace DLS {
144      /**      /**
145       * Apply articulation connections to the respective RIFF chunks. You       * Apply articulation connections to the respective RIFF chunks. You
146       * have to call File::Save() to make changes persistent.       * have to call File::Save() to make changes persistent.
147         *
148         * @param pProgress - callback function for progress notification
149       */       */
150      void Articulation::UpdateChunks() {      void Articulation::UpdateChunks(progress_t* pProgress) {
151          const int iEntrySize = 12; // 12 bytes per connection block          const int iEntrySize = 12; // 12 bytes per connection block
152          pArticulationCk->Resize(HeaderSize + Connections * iEntrySize);          pArticulationCk->Resize(HeaderSize + Connections * iEntrySize);
153          uint8_t* pData = (uint8_t*) pArticulationCk->LoadChunkData();          uint8_t* pData = (uint8_t*) pArticulationCk->LoadChunkData();
# Line 217  namespace DLS { Line 219  namespace DLS {
219      /**      /**
220       * Apply all articulations to the respective RIFF chunks. You have to       * Apply all articulations to the respective RIFF chunks. You have to
221       * call File::Save() to make changes persistent.       * call File::Save() to make changes persistent.
222         *
223         * @param pProgress - callback function for progress notification
224       */       */
225      void Articulator::UpdateChunks() {      void Articulator::UpdateChunks(progress_t* pProgress) {
226          if (pArticulations) {          if (pArticulations) {
227              ArticulationList::iterator iter = pArticulations->begin();              ArticulationList::iterator iter = pArticulations->begin();
228              ArticulationList::iterator end  = pArticulations->end();              ArticulationList::iterator end  = pArticulations->end();
229              for (; iter != end; ++iter) {              for (; iter != end; ++iter) {
230                  (*iter)->UpdateChunks();                  (*iter)->UpdateChunks(pProgress);
231              }              }
232          }          }
233      }      }
# Line 336  namespace DLS { Line 340  namespace DLS {
340       *       *
341       * Apply current INFO field values to the respective INFO chunks. You       * Apply current INFO field values to the respective INFO chunks. You
342       * have to call File::Save() to make changes persistent.       * have to call File::Save() to make changes persistent.
343         *
344         * @param pProgress - callback function for progress notification
345       */       */
346      void Info::UpdateChunks() {      void Info::UpdateChunks(progress_t* pProgress) {
347          if (!pResourceListChunk) return;          if (!pResourceListChunk) return;
348    
349          // make sure INFO list chunk exists          // make sure INFO list chunk exists
# Line 464  namespace DLS { Line 470  namespace DLS {
470       * will not be applied at the moment (yet).       * will not be applied at the moment (yet).
471       *       *
472       * You have to call File::Save() to make changes persistent.       * You have to call File::Save() to make changes persistent.
473         *
474         * @param pProgress - callback function for progress notification
475       */       */
476      void Resource::UpdateChunks() {      void Resource::UpdateChunks(progress_t* pProgress) {
477          pInfo->UpdateChunks();          pInfo->UpdateChunks(pProgress);
478    
479          if (pDLSID) {          if (pDLSID) {
480              // make sure 'dlid' chunk exists              // make sure 'dlid' chunk exists
# Line 582  namespace DLS { Line 590  namespace DLS {
590      /**      /**
591       * Apply all sample player options to the respective RIFF chunk. You       * Apply all sample player options to the respective RIFF chunk. You
592       * have to call File::Save() to make changes persistent.       * have to call File::Save() to make changes persistent.
593         *
594         * @param pProgress - callback function for progress notification
595       */       */
596      void Sampler::UpdateChunks() {      void Sampler::UpdateChunks(progress_t* pProgress) {
597          // make sure 'wsmp' chunk exists          // make sure 'wsmp' chunk exists
598          RIFF::Chunk* wsmp = pParentList->GetSubChunk(CHUNK_ID_WSMP);          RIFF::Chunk* wsmp = pParentList->GetSubChunk(CHUNK_ID_WSMP);
599          int wsmpSize = uiHeaderSize + SampleLoops * 16;          int wsmpSize = uiHeaderSize + SampleLoops * 16;
# Line 951  namespace DLS { Line 961  namespace DLS {
961       * Apply sample and its settings to the respective RIFF chunks. You have       * Apply sample and its settings to the respective RIFF chunks. You have
962       * to call File::Save() to make changes persistent.       * to call File::Save() to make changes persistent.
963       *       *
964         * @param pProgress - callback function for progress notification
965       * @throws Exception if FormatTag != DLS_WAVE_FORMAT_PCM or no sample data       * @throws Exception if FormatTag != DLS_WAVE_FORMAT_PCM or no sample data
966       *                   was provided yet       *                   was provided yet
967       */       */
968      void Sample::UpdateChunks() {      void Sample::UpdateChunks(progress_t* pProgress) {
969          if (FormatTag != DLS_WAVE_FORMAT_PCM)          if (FormatTag != DLS_WAVE_FORMAT_PCM)
970              throw Exception("Could not save sample, only PCM format is supported");              throw Exception("Could not save sample, only PCM format is supported");
971          // 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
972          if (!pCkData)          if (!pCkData)
973              throw Exception("Could not save sample, there is no sample data to save");              throw Exception("Could not save sample, there is no sample data to save");
974          // update chunks of base class as well          // update chunks of base class as well
975          Resource::UpdateChunks();          Resource::UpdateChunks(pProgress);
976          // make sure 'fmt' chunk exists          // make sure 'fmt' chunk exists
977          RIFF::Chunk* pCkFormat = pWaveList->GetSubChunk(CHUNK_ID_FMT);          RIFF::Chunk* pCkFormat = pWaveList->GetSubChunk(CHUNK_ID_FMT);
978          if (!pCkFormat) pCkFormat = pWaveList->AddSubChunk(CHUNK_ID_FMT, 16); // assumes PCM format          if (!pCkFormat) pCkFormat = pWaveList->AddSubChunk(CHUNK_ID_FMT, 16); // assumes PCM format
# Line 1094  namespace DLS { Line 1105  namespace DLS {
1105       * Apply Region settings to the respective RIFF chunks. You have to       * Apply Region settings to the respective RIFF chunks. You have to
1106       * call File::Save() to make changes persistent.       * call File::Save() to make changes persistent.
1107       *       *
1108         * @param pProgress - callback function for progress notification
1109       * @throws Exception - if the Region's sample could not be found       * @throws Exception - if the Region's sample could not be found
1110       */       */
1111      void Region::UpdateChunks() {      void Region::UpdateChunks(progress_t* pProgress) {
1112          // make sure 'rgnh' chunk exists          // make sure 'rgnh' chunk exists
1113          RIFF::Chunk* rgnh = pCkRegion->GetSubChunk(CHUNK_ID_RGNH);          RIFF::Chunk* rgnh = pCkRegion->GetSubChunk(CHUNK_ID_RGNH);
1114          if (!rgnh) rgnh = pCkRegion->AddSubChunk(CHUNK_ID_RGNH, Layer ? 14 : 12);          if (!rgnh) rgnh = pCkRegion->AddSubChunk(CHUNK_ID_RGNH, Layer ? 14 : 12);
# Line 1115  namespace DLS { Line 1127  namespace DLS {
1127    
1128          // update chunks of base classes as well (but skip Resource,          // update chunks of base classes as well (but skip Resource,
1129          // as a rgn doesn't seem to have dlid and INFO chunks)          // as a rgn doesn't seem to have dlid and INFO chunks)
1130          Articulator::UpdateChunks();          Articulator::UpdateChunks(pProgress);
1131          Sampler::UpdateChunks();          Sampler::UpdateChunks(pProgress);
1132    
1133          // make sure 'wlnk' chunk exists          // make sure 'wlnk' chunk exists
1134          RIFF::Chunk* wlnk = pCkRegion->GetSubChunk(CHUNK_ID_WLNK);          RIFF::Chunk* wlnk = pCkRegion->GetSubChunk(CHUNK_ID_WLNK);
# Line 1269  namespace DLS { Line 1281  namespace DLS {
1281    
1282      void Instrument::MoveRegion(Region* pSrc, Region* pDst) {      void Instrument::MoveRegion(Region* pSrc, Region* pDst) {
1283          RIFF::List* lrgn = pCkInstrument->GetSubList(LIST_TYPE_LRGN);          RIFF::List* lrgn = pCkInstrument->GetSubList(LIST_TYPE_LRGN);
1284          lrgn->MoveSubChunk(pSrc->pCkRegion, pDst ? pDst->pCkRegion : 0);          lrgn->MoveSubChunk(pSrc->pCkRegion, (RIFF::Chunk*) (pDst ? pDst->pCkRegion : 0));
1285    
1286          pRegions->remove(pSrc);          pRegions->remove(pSrc);
1287          RegionList::iterator iter = find(pRegions->begin(), pRegions->end(), pDst);          RegionList::iterator iter = find(pRegions->begin(), pRegions->end(), pDst);
# Line 1289  namespace DLS { Line 1301  namespace DLS {
1301       * Apply Instrument with all its Regions to the respective RIFF chunks.       * Apply Instrument with all its Regions to the respective RIFF chunks.
1302       * You have to call File::Save() to make changes persistent.       * You have to call File::Save() to make changes persistent.
1303       *       *
1304         * @param pProgress - callback function for progress notification
1305       * @throws Exception - on errors       * @throws Exception - on errors
1306       */       */
1307      void Instrument::UpdateChunks() {      void Instrument::UpdateChunks(progress_t* pProgress) {
1308          // first update base classes' chunks          // first update base classes' chunks
1309          Resource::UpdateChunks();          Resource::UpdateChunks(pProgress);
1310          Articulator::UpdateChunks();          Articulator::UpdateChunks(pProgress);
1311          // make sure 'insh' chunk exists          // make sure 'insh' chunk exists
1312          RIFF::Chunk* insh = pCkInstrument->GetSubChunk(CHUNK_ID_INSH);          RIFF::Chunk* insh = pCkInstrument->GetSubChunk(CHUNK_ID_INSH);
1313          if (!insh) insh = pCkInstrument->AddSubChunk(CHUNK_ID_INSH, 12);          if (!insh) insh = pCkInstrument->AddSubChunk(CHUNK_ID_INSH, 12);
# Line 1313  namespace DLS { Line 1326  namespace DLS {
1326          if (!pRegions) return;          if (!pRegions) return;
1327          RegionList::iterator iter = pRegions->begin();          RegionList::iterator iter = pRegions->begin();
1328          RegionList::iterator end  = pRegions->end();          RegionList::iterator end  = pRegions->end();
1329          for (; iter != end; ++iter) {          for (int i = 0; iter != end; ++iter, ++i) {
1330              (*iter)->UpdateChunks();              // divide local progress into subprogress
1331                progress_t subprogress;
1332                __divide_progress(pProgress, &subprogress, pRegions->size(), i);
1333                // do the actual work
1334                (*iter)->UpdateChunks(&subprogress);
1335          }          }
1336            __notify_progress(pProgress, 1.0); // notify done
1337      }      }
1338    
1339      /** @brief Destructor.      /** @brief Destructor.
# Line 1449  namespace DLS { Line 1467  namespace DLS {
1467                  for (int i = 0 ; i < WavePoolCount ; i++) {                  for (int i = 0 ; i < WavePoolCount ; i++) {
1468                      pWavePoolTableHi[i] = ptbl->ReadUint32();                      pWavePoolTableHi[i] = ptbl->ReadUint32();
1469                      pWavePoolTable[i] = ptbl->ReadUint32();                      pWavePoolTable[i] = ptbl->ReadUint32();
1470                      if (pWavePoolTable[i] & 0x80000000)                      //NOTE: disabled this 2GB check, not sure why this check was still left here (Christian, 2016-05-12)
1471                          throw DLS::Exception("Files larger than 2 GB not yet supported");                      //if (pWavePoolTable[i] & 0x80000000)
1472                        //    throw DLS::Exception("Files larger than 2 GB not yet supported");
1473                  }                  }
1474              } else { // conventional 32 bit offsets              } else { // conventional 32 bit offsets
1475                  ptbl->Read(pWavePoolTable, WavePoolCount, sizeof(uint32_t));                  ptbl->Read(pWavePoolTable, WavePoolCount, sizeof(uint32_t));
# Line 1671  namespace DLS { Line 1690  namespace DLS {
1690       * the respective RIFF chunks. You have to call Save() to make changes       * the respective RIFF chunks. You have to call Save() to make changes
1691       * persistent.       * persistent.
1692       *       *
1693         * @param pProgress - callback function for progress notification
1694       * @throws Exception - on errors       * @throws Exception - on errors
1695       */       */
1696      void File::UpdateChunks() {      void File::UpdateChunks(progress_t* pProgress) {
1697          // first update base class's chunks          // first update base class's chunks
1698          Resource::UpdateChunks();          Resource::UpdateChunks(pProgress);
1699    
1700          // if version struct exists, update 'vers' chunk          // if version struct exists, update 'vers' chunk
1701          if (pVersion) {          if (pVersion) {
# Line 1697  namespace DLS { Line 1717  namespace DLS {
1717    
1718          // update instrument's chunks          // update instrument's chunks
1719          if (pInstruments) {          if (pInstruments) {
1720                // divide local progress into subprogress
1721                progress_t subprogress;
1722                __divide_progress(pProgress, &subprogress, 20.f, 0.f); // arbitrarily subdivided into 5% of total progress
1723    
1724                // do the actual work
1725              InstrumentList::iterator iter = pInstruments->begin();              InstrumentList::iterator iter = pInstruments->begin();
1726              InstrumentList::iterator end  = pInstruments->end();              InstrumentList::iterator end  = pInstruments->end();
1727              for (; iter != end; ++iter) {              for (int i = 0; iter != end; ++iter, ++i) {
1728                  (*iter)->UpdateChunks();                  // divide subprogress into sub-subprogress
1729                    progress_t subsubprogress;
1730                    __divide_progress(&subprogress, &subsubprogress, pInstruments->size(), i);
1731                    // do the actual work
1732                    (*iter)->UpdateChunks(&subsubprogress);
1733              }              }
1734    
1735                __notify_progress(&subprogress, 1.0); // notify subprogress done
1736          }          }
1737    
1738          // update 'ptbl' chunk          // update 'ptbl' chunk
# Line 1719  namespace DLS { Line 1750  namespace DLS {
1750    
1751          // update sample's chunks          // update sample's chunks
1752          if (pSamples) {          if (pSamples) {
1753                // divide local progress into subprogress
1754                progress_t subprogress;
1755                __divide_progress(pProgress, &subprogress, 20.f, 1.f); // arbitrarily subdivided into 95% of total progress
1756    
1757                // do the actual work
1758              SampleList::iterator iter = pSamples->begin();              SampleList::iterator iter = pSamples->begin();
1759              SampleList::iterator end  = pSamples->end();              SampleList::iterator end  = pSamples->end();
1760              for (; iter != end; ++iter) {              for (int i = 0; iter != end; ++iter, ++i) {
1761                  (*iter)->UpdateChunks();                  // divide subprogress into sub-subprogress
1762                    progress_t subsubprogress;
1763                    __divide_progress(&subprogress, &subsubprogress, pSamples->size(), i);
1764                    // do the actual work
1765                    (*iter)->UpdateChunks(&subsubprogress);
1766              }              }
1767    
1768                __notify_progress(&subprogress, 1.0); // notify subprogress done
1769          }          }
1770    
1771            __notify_progress(pProgress, 1.0); // notify done
1772      }      }
1773    
1774      /** @brief Save changes to another file.      /** @brief Save changes to another file.
# Line 1739  namespace DLS { Line 1783  namespace DLS {
1783       * the new file (given by \a Path) afterwards.       * the new file (given by \a Path) afterwards.
1784       *       *
1785       * @param Path - path and file name where everything should be written to       * @param Path - path and file name where everything should be written to
1786         * @param pProgress - optional: callback function for progress notification
1787       */       */
1788      void File::Save(const String& Path) {      void File::Save(const String& Path, progress_t* pProgress) {
1789          UpdateChunks();          {
1790          pRIFF->Save(Path);              // divide local progress into subprogress
1791                progress_t subprogress;
1792                __divide_progress(pProgress, &subprogress, 2.f, 0.f); // arbitrarily subdivided into 50% of total progress
1793                // do the actual work
1794                UpdateChunks(&subprogress);
1795                
1796            }
1797            {
1798                // divide local progress into subprogress
1799                progress_t subprogress;
1800                __divide_progress(pProgress, &subprogress, 2.f, 1.f); // arbitrarily subdivided into 50% of total progress
1801                // do the actual work
1802                pRIFF->Save(Path, &subprogress);
1803            }
1804          UpdateFileOffsets();          UpdateFileOffsets();
1805            __notify_progress(pProgress, 1.0); // notify done
1806      }      }
1807    
1808      /** @brief Save changes to same file.      /** @brief Save changes to same file.
# Line 1752  namespace DLS { Line 1811  namespace DLS {
1811       * file. The file might temporarily grow to a higher size than it will       * file. The file might temporarily grow to a higher size than it will
1812       * have at the end of the saving process.       * have at the end of the saving process.
1813       *       *
1814         * @param pProgress - optional: callback function for progress notification
1815       * @throws RIFF::Exception if any kind of IO error occured       * @throws RIFF::Exception if any kind of IO error occured
1816       * @throws DLS::Exception  if any kind of DLS specific error occured       * @throws DLS::Exception  if any kind of DLS specific error occured
1817       */       */
1818      void File::Save() {      void File::Save(progress_t* pProgress) {
1819          UpdateChunks();          {
1820          pRIFF->Save();              // divide local progress into subprogress
1821                progress_t subprogress;
1822                __divide_progress(pProgress, &subprogress, 2.f, 0.f); // arbitrarily subdivided into 50% of total progress
1823                // do the actual work
1824                UpdateChunks(&subprogress);
1825            }
1826            {
1827                // divide local progress into subprogress
1828                progress_t subprogress;
1829                __divide_progress(pProgress, &subprogress, 2.f, 1.f); // arbitrarily subdivided into 50% of total progress
1830                // do the actual work
1831                pRIFF->Save(&subprogress);
1832            }
1833          UpdateFileOffsets();          UpdateFileOffsets();
1834            __notify_progress(pProgress, 1.0); // notify done
1835      }      }
1836    
1837      /** @brief Updates all file offsets stored all over the file.      /** @brief Updates all file offsets stored all over the file.

Legend:
Removed from v.2609  
changed lines
  Added in v.2909

  ViewVC Help
Powered by ViewVC