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

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

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

revision 365 by persson, Thu Feb 10 19:16:31 2005 UTC revision 902 by persson, Sat Jul 22 14:22:01 2006 UTC
# Line 2  Line 2 
2   *                                                                         *   *                                                                         *
3   *   libgig - C++ cross-platform Gigasampler format file loader library    *   *   libgig - C++ cross-platform Gigasampler format file loader library    *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003, 2004 by Christian Schoenebeck                     *   *   Copyright (C) 2003-2005 by Christian Schoenebeck                      *
6   *                               <cuse@users.sourceforge.net>              *   *                              <cuse@users.sourceforge.net>               *
7   *                                                                         *   *                                                                         *
8   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
9   *   it under the terms of the GNU General Public License as published by  *   *   it under the terms of the GNU General Public License as published by  *
# Line 40  Line 40 
40  #include <iostream>  #include <iostream>
41  #include <cstdlib>  #include <cstdlib>
42  #include <string.h>  #include <string.h>
43    #include <string>
44  #include <stdlib.h>  #include <stdlib.h>
45  #include <sys/types.h>  #include <sys/types.h>
46  #include <sys/stat.h>  #include <sys/stat.h>
# Line 52  Line 53 
53  # define HAVE_SNDFILE 1  # define HAVE_SNDFILE 1
54  #endif // WIN32  #endif // WIN32
55    
56    // abort compilation here if neither libsndfile nor libaudiofile are available
57    #if !HAVE_SNDFILE && !HAVE_AUDIOFILE
58    # error "Neither libsndfile nor libaudiofile seem to be available!"
59    # error "(HAVE_SNDFILE and HAVE_AUDIOFILE are both false)"
60    #endif
61    
62  // we prefer libsndfile before libaudiofile  // we prefer libsndfile before libaudiofile
63  #if HAVE_SNDFILE  #if HAVE_SNDFILE
64  # include <sndfile.h>  # include <sndfile.h>
# Line 66  using namespace std; Line 73  using namespace std;
73  typedef map<unsigned int, bool> OrderMap;  typedef map<unsigned int, bool> OrderMap;
74  OrderMap* pOrderedSamples = NULL;  OrderMap* pOrderedSamples = NULL;
75    
76    string Revision();
77    void PrintVersion();
78  void PrintUsage();  void PrintUsage();
79  void ExtractSamples(gig::File* gig, char* destdir, OrderMap* ordered);  void ExtractSamples(gig::File* gig, char* destdir, OrderMap* ordered);
80  int writeWav(const char* filename, void* samples, long samplecount, int channels, int bitdepth, long rate);  int writeWav(const char* filename, void* samples, long samplecount, int channels, int bitdepth, long rate);
81  string ToString(int i);  string ToString(int i);
82    
83  #ifndef HAVE_SNDFILE  #if !HAVE_SNDFILE // use libaudiofile
84  void* hAFlib; // handle to libaudiofile  void* hAFlib; // handle to libaudiofile
85  void openAFlib(void);  void openAFlib(void);
86  void closeAFlib(void);  void closeAFlib(void);
# Line 88  int(*_afCloseFile)(AFfilehandle file); Line 97  int(*_afCloseFile)(AFfilehandle file);
97  #endif // !HAVE_SNDFILE  #endif // !HAVE_SNDFILE
98    
99  int main(int argc, char *argv[]) {  int main(int argc, char *argv[]) {
100         if (argc >= 2) {
101            if (argv[1][0] == '-') {
102                switch (argv[1][1]) {
103                    case 'v':
104                        PrintVersion();
105                        return EXIT_SUCCESS;
106                }
107            }
108        }
109      if (argc < 3) {      if (argc < 3) {
110          PrintUsage();          PrintUsage();
111          return EXIT_FAILURE;          return EXIT_FAILURE;
# Line 149  int main(int argc, char *argv[]) { Line 167  int main(int argc, char *argv[]) {
167  }  }
168    
169  void ExtractSamples(gig::File* gig, char* destdir, OrderMap* ordered) {  void ExtractSamples(gig::File* gig, char* destdir, OrderMap* ordered) {
170  #ifndef HAVE_SNDFILE  #if !HAVE_SNDFILE // use libaudiofile
171      hAFlib = NULL;      hAFlib = NULL;
172      openAFlib();      openAFlib();
173  #endif // !HAVE_SNDFILE  #endif // !HAVE_SNDFILE
174      uint8_t* pWave  = NULL;      uint8_t* pWave  = NULL;
175        int* pIntWave = NULL;
176      long BufferSize = 0;      long BufferSize = 0;
177      int samples     = 0;      int samples     = 0;
178        gig::buffer_t decompressionBuffer;
179        decompressionBuffer.Size = 0;
180        unsigned long decompressionBufferSize = 0;
181      cout << "Seeking for available samples..." << flush;      cout << "Seeking for available samples..." << flush;
182      gig::Sample* pSample = gig->GetFirstSample();      gig::Sample* pSample = gig->GetFirstSample();
183      cout << "OK" << endl << flush;      cout << "OK" << endl << flush;
# Line 188  void ExtractSamples(gig::File* gig, char Line 210  void ExtractSamples(gig::File* gig, char
210    
211    
212  #if USE_DISK_STREAMING  #if USE_DISK_STREAMING
213          long neededsize = (pSample->Compressed) ? 10485760 /* 10 MB buffer */          long neededsize = pSample->BitDepth == 24 ?
214                                                  : pSample->SamplesTotal * pSample->FrameSize;              pSample->SamplesTotal * pSample->Channels * sizeof(int) :
215                pSample->SamplesTotal * pSample->FrameSize;
216          if (BufferSize < neededsize) {          if (BufferSize < neededsize) {
217              if (pWave) delete[] pWave;              if (pWave) delete[] pWave;
218              pWave = new uint8_t[neededsize];              pWave = new uint8_t[neededsize];
219              BufferSize = neededsize;              BufferSize = neededsize;
220          }          }
221            pIntWave = (int*)pWave;
222  #  if HASHED_READS_TEST  #  if HASHED_READS_TEST
223          unsigned long readsamples     = 0,          unsigned long readinthisrun   = 0,
                       readinthisrun   = 0,  
224                        samplepiecesize = 2000;                        samplepiecesize = 2000;
225          uint8_t* pSamplePiece = pWave;          uint8_t* pSamplePiece = pWave;
226          do { // we read the sample in small pieces and increment the size with each run just to test streaming capability          do { // we read the sample in small pieces and increment the size with each run just to test streaming capability
227              readinthisrun = pSample->Read(pSamplePiece, ++samplepiecesize);              readinthisrun = pSample->Read(pSamplePiece, ++samplepiecesize);
228              // 24 bit is truncated to 16 by Sample::Read at the moment              pSamplePiece += readinthisrun * pSample->FrameSize;
             pSamplePiece += readinthisrun * (2 * pSample->Channels); // readinthisrun * pSample->FrameSize;  
             readsamples  += readinthisrun;  
229          } while (readinthisrun == samplepiecesize);          } while (readinthisrun == samplepiecesize);
230    
         if (pSample->Compressed) { // hack  
             pSample->SamplesTotal = readsamples;  
             pSample->BitDepth = 16;  
         }  
231  #  else // read in one piece  #  else // read in one piece
232          if (pSample->Compressed) {          if (pSample->Compressed) {
233              pSample->SamplesTotal = pSample->Read(pWave, 10485760 >> 2); // assumes 16 bit stereo              if (decompressionBufferSize < pSample->SamplesTotal) {
234          }                  gig::Sample::DestroyDecompressionBuffer(decompressionBuffer);
235          else {                  decompressionBuffer = gig::Sample::CreateDecompressionBuffer(pSample->SamplesTotal);
236                    decompressionBufferSize = pSample->SamplesTotal;
237                }
238                pSample->Read(pWave, pSample->SamplesTotal, &decompressionBuffer);
239            } else {
240              pSample->Read(pWave, pSample->SamplesTotal);              pSample->Read(pWave, pSample->SamplesTotal);
241          }          }
242  #  endif // HASHED_READS_TEST  #  endif // HASHED_READS_TEST
243  #else // no disk streaming  #else // no disk streaming
244          if (pSample->Compressed) {          if (pSample->Compressed) {
245              cout << "Sorry, sample is compressed and Sample::LoadSampleData() has no decompression routine yet! - Solution: set USE_DISK_STREAMING in gigextract.cpp (line 29) to 1 and recompile!" << endl;              cout << "Sorry, sample is compressed and Sample::LoadSampleData() only decompresses the beginning of the sample - Solution: set USE_DISK_STREAMING in gigextract.cpp (line 32) to 1 and recompile!" << endl;
246            } else {
247                gig::buffer_t buffer = pSample->LoadSampleData(); // load wave into RAM
248                pWave = static_cast<uint8_t*>(buffer.pStart);
249                if (pSample->BitDepth == 24) {
250                    long neededsize = pSample->SamplesTotal * pSample->Channels;
251                    if (BufferSize < neededsize) {
252                        if (pIntWave) delete[] pIntWave;
253                        pIntWave = new int[neededsize];
254                        BufferSize = neededsize;
255                    }
256                }
257          }          }
         else pWave = (uint8_t*) pSample->LoadSampleData(); // load wave into RAM  
258  #endif // USE_DISK_STREAMING  #endif // USE_DISK_STREAMING
259          if (pWave) {          if (pWave) {
260    
261                // Both libsndfile and libaudiofile uses int for 24 bit
262                // samples. libgig however returns 3 bytes per sample, so
263                // we have to convert the wave data before writing.
264                if (pSample->BitDepth == 24) {
265                    int n = pSample->SamplesTotal * pSample->Channels;
266                    for (int i = n - 1 ; i >= 0 ; i--) {
267    #if HAVE_SNDFILE
268                        pIntWave[i] = pWave[i * 3] << 8 | pWave[i * 3 + 1] << 16 | pWave[i * 3 + 2] << 24;
269    #else
270                        pIntWave[i] = pWave[i * 3] | pWave[i * 3 + 1] << 8 | pWave[i * 3 + 2] << 16;
271    #endif
272                    }
273                }
274    
275              int res = writeWav(filename.c_str(),              int res = writeWav(filename.c_str(),
276                                 pWave,                                 pSample->BitDepth == 24 ? static_cast<void*>(pIntWave) : pWave,
277                                 pSample->SamplesTotal,                                 pSample->SamplesTotal,
278                                 pSample->Channels,                                 pSample->Channels,
279                                 pSample->BitDepth,                                 pSample->BitDepth,
# Line 240  void ExtractSamples(gig::File* gig, char Line 286  void ExtractSamples(gig::File* gig, char
286    
287          pSample = gig->GetNextSample();          pSample = gig->GetNextSample();
288      }      }
289      if (pWave) delete[] (uint8_t*) pWave;      gig::Sample::DestroyDecompressionBuffer(decompressionBuffer);
290  #ifndef HAVE_SNDFILE  #if USE_DISK_STREAMING
291        if (pWave) delete[] pWave;
292    #else
293        if (pIntWave) delete[] pIntWave;
294    #endif
295    #if !HAVE_SNDFILE // use libaudiofile
296      closeAFlib();      closeAFlib();
297  #endif // !HAVE_SNDFILE  #endif // !HAVE_SNDFILE
298  }  }
# Line 254  int writeWav(const char* filename, void* Line 305  int writeWav(const char* filename, void*
305      switch (bitdepth) {      switch (bitdepth) {
306          case 8:          case 8:
307              format |= SF_FORMAT_PCM_S8;              format |= SF_FORMAT_PCM_S8;
             cout << "8 bit" << endl << flush;  
308              break;              break;
309          case 16:          case 16:
310              format |= SF_FORMAT_PCM_16;              format |= SF_FORMAT_PCM_16;
             cout << "16 bit" << endl << flush;  
311              break;              break;
312          case 24:          case 24:
313              format |= SF_FORMAT_PCM_24;              format |= SF_FORMAT_PCM_24;
             cout << "24 bit" << endl << flush;  
314              break;              break;
315          case 32:          case 32:
316              format |= SF_FORMAT_PCM_32;              format |= SF_FORMAT_PCM_32;
             cout << "32 bit" << endl << flush;  
317              break;              break;
318          default:          default:
319              cerr << "Error: Bithdepth " << ToString(bitdepth) << " not supported by libsndfile, ignoring sample!\n" << flush;              cerr << "Error: Bithdepth " << ToString(bitdepth) << " not supported by libsndfile, ignoring sample!\n" << flush;
# Line 281  int writeWav(const char* filename, void* Line 328  int writeWav(const char* filename, void*
328          cerr << "Error: Unable to open output file \'" << filename << "\'.\n" << flush;          cerr << "Error: Unable to open output file \'" << filename << "\'.\n" << flush;
329          return -1;          return -1;
330      }      }
331      if (sf_write_short(hfile, (short*)samples, channels * samplecount) != channels * samplecount) {      sf_count_t res = bitdepth == 24 ?
332            sf_write_int(hfile, static_cast<int*>(samples), channels * samplecount) :
333            sf_write_short(hfile, static_cast<short*>(samples), channels * samplecount);
334        if (res != channels * samplecount) {
335          cerr << sf_strerror(hfile) << endl << flush;          cerr << sf_strerror(hfile) << endl << flush;
336          sf_close(hfile);          sf_close(hfile);
337          return -1;          return -1;
338      }      }
339      sf_close(hfile);      sf_close(hfile);
340  #else  #else // use libaudiofile
341      AFfilesetup setup = _afNewFileSetup();      AFfilesetup setup = _afNewFileSetup();
342      _afInitFileFormat(setup, AF_FILE_WAVE);      _afInitFileFormat(setup, AF_FILE_WAVE);
343      _afInitChannels(setup, AF_DEFAULT_TRACK, channels);      _afInitChannels(setup, AF_DEFAULT_TRACK, channels);
# Line 304  int writeWav(const char* filename, void* Line 354  int writeWav(const char* filename, void*
354      return 0; // success      return 0; // success
355  }  }
356    
357  #ifndef HAVE_SNDFILE  #if !HAVE_SNDFILE // use libaudiofile
358  void openAFlib() {  void openAFlib() {
359      hAFlib = dlopen("libaudiofile.so", RTLD_NOW);      hAFlib = dlopen("libaudiofile.so", RTLD_NOW);
360      if (!hAFlib) {      if (!hAFlib) {
# Line 328  void closeAFlib() { Line 378  void closeAFlib() {
378  }  }
379  #endif // !HAVE_SNDFILE  #endif // !HAVE_SNDFILE
380    
381    string Revision() {
382        string s = "$Revision: 1.8 $";
383        return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
384    }
385    
386    void PrintVersion() {
387        cout << "gigextract revision " << Revision() << endl;
388        cout << "using " << gig::libraryName() << " " << gig::libraryVersion();
389        #if HAVE_SNDFILE
390        char versionBuffer[128];
391        sf_command(NULL, SFC_GET_LIB_VERSION, versionBuffer, 128);
392        cout << ", " << versionBuffer;
393        #else // use libaudiofile
394        cout << "\nbuilt against libaudiofile "
395             << LIBAUDIOFILE_MAJOR_VERSION << "." << LIBAUDIOFILE_MINOR_VERSION;
396        # ifdef LIBAUDIOFILE_MICRO_VERSION
397        cout << "." << LIBAUDIOFILE_MICRO_VERSION;
398        # endif // LIBAUDIOFILE_MICRO_VERSION
399        #endif // HAVE_SNDFILE
400        cout << endl;
401    }
402    
403  void PrintUsage() {  void PrintUsage() {
404      cout << "gigextract - extracts samples from a Gigasampler file." << endl;      cout << "gigextract - extracts samples from a Gigasampler file." << endl;
405      cout << endl;      cout << endl;
406      cout << "Usage: gigextract GIGFILE DESTDIR [SAMPLENR] [ [SAMPLENR] ...]" << endl;      cout << "Usage: gigextract [-v] GIGFILE DESTDIR [SAMPLENR] [ [SAMPLENR] ...]" << endl;
407      cout << endl;      cout << endl;
408      cout << "   GIGFILE  Input Gigasampler (.gig) file." << endl;      cout << "   GIGFILE  Input Gigasampler (.gig) file." << endl;
409      cout << endl;      cout << endl;
# Line 341  void PrintUsage() { Line 413  void PrintUsage() {
413      cout << "            If no sample indices are given, all samples will be extracted" << endl;      cout << "            If no sample indices are given, all samples will be extracted" << endl;
414      cout << "            (use gigdump to look for available samples)." << endl;      cout << "            (use gigdump to look for available samples)." << endl;
415      cout << endl;      cout << endl;
416        cout << "   -v       Print version and exit." << endl;
417        cout << endl;
418  }  }
419    
420  string ToString(int i) {  string ToString(int i) {

Legend:
Removed from v.365  
changed lines
  Added in v.902

  ViewVC Help
Powered by ViewVC