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

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

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

revision 549 by schoenebeck, Mon May 16 18:40:45 2005 UTC revision 1953 by schoenebeck, Thu Jul 30 08:16:02 2009 UTC
# Line 1  Line 1 
1  /***************************************************************************  /***************************************************************************
2   *                                                                         *   *                                                                         *
3   *   libgig - C++ cross-platform Gigasampler format file loader library    *   *   libgig - C++ cross-platform Gigasampler format file access library    *
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003-2005 by Christian Schoenebeck                      *   *   Copyright (C) 2003-2009 by Christian Schoenebeck                      *
6   *                              <cuse@users.sourceforge.net>               *   *                              <cuse@users.sourceforge.net>               *
7   *                                                                         *   *                                                                         *
8     *   This program is part of libgig.                                       *
9     *                                                                         *
10   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
11   *   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  *
12   *   the Free Software Foundation; either version 2 of the License, or     *   *   the Free Software Foundation; either version 2 of the License, or     *
# Line 44  Line 46 
46  #include <stdlib.h>  #include <stdlib.h>
47  #include <sys/types.h>  #include <sys/types.h>
48  #include <sys/stat.h>  #include <sys/stat.h>
 #include <dirent.h>  
49  #include <errno.h>  #include <errno.h>
50  #include <dlfcn.h>  
51    #include "gig.h"
52    
53    #ifdef _MSC_VER
54    #define S_ISDIR(x) (S_IFDIR & (x))
55    #define S_IWUSR S_IWRITE
56    #define S_IXUSR S_IEXEC
57    #endif
58    
59    #if POSIX
60    # include <dlfcn.h>
61    #endif
62    
63  // only libsndfile is available for Windows, so we use that for writing the sound files  // only libsndfile is available for Windows, so we use that for writing the sound files
64  #ifdef WIN32  #ifdef WIN32
65  # define HAVE_SNDFILE 1  # define HAVE_SNDFILE 1
66  #endif // WIN32  #endif // WIN32
67    
68    // abort compilation here if neither libsndfile nor libaudiofile are available
69    #if !HAVE_SNDFILE && !HAVE_AUDIOFILE
70    # error "Neither libsndfile nor libaudiofile seem to be available!"
71    # error "(HAVE_SNDFILE and HAVE_AUDIOFILE are both false)"
72    #endif
73    
74  // we prefer libsndfile before libaudiofile  // we prefer libsndfile before libaudiofile
75  #if HAVE_SNDFILE  #if HAVE_SNDFILE
76  # include <sndfile.h>  # include <sndfile.h>
# Line 60  Line 78 
78  # include <audiofile.h>  # include <audiofile.h>
79  #endif // HAVE_SNDFILE  #endif // HAVE_SNDFILE
80    
 #include "gig.h"  
   
81  using namespace std;  using namespace std;
82    
83  typedef map<unsigned int, bool> OrderMap;  typedef map<unsigned int, bool> OrderMap;
# Line 74  void ExtractSamples(gig::File* gig, char Line 90  void ExtractSamples(gig::File* gig, char
90  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);
91  string ToString(int i);  string ToString(int i);
92    
93  #ifndef HAVE_SNDFILE  #if !HAVE_SNDFILE // use libaudiofile
94  void* hAFlib; // handle to libaudiofile  void* hAFlib; // handle to libaudiofile
95  void openAFlib(void);  void openAFlib(void);
96  void closeAFlib(void);  void closeAFlib(void);
# Line 117  int main(int argc, char *argv[]) { Line 133  int main(int argc, char *argv[]) {
133          return EXIT_FAILURE;          return EXIT_FAILURE;
134      }      }
135      fclose(hFile);      fclose(hFile);
136      DIR* dir = opendir(argv[2]);      struct stat buf;
137      if (!dir) {      if (stat(argv[2], &buf) == -1) {
138          cout << "Unable to open DESTDIR: ";          cout << "Unable to open DESTDIR: ";
139          switch (errno) {          switch (errno) {
140              case EACCES:  cout << "Permission denied." << endl;              case EACCES:  cout << "Permission denied." << endl;
141                            break;                            break;
             case EMFILE:  cout << "Too many file descriptors in use by process." << endl;  
                           break;  
             case ENFILE:  cout << "Too many files are currently open in the system." << endl;  
                           break;  
142              case ENOENT:  cout << "Directory does not exist, or name is an empty string." << endl;              case ENOENT:  cout << "Directory does not exist, or name is an empty string." << endl;
143                            break;                            break;
144              case ENOMEM:  cout << "Insufficient memory to complete the operation." << endl;              case ENOMEM:  cout << "Insufficient memory to complete the operation." << endl;
# Line 136  int main(int argc, char *argv[]) { Line 148  int main(int argc, char *argv[]) {
148              default:      cout << "Unknown error" << endl;              default:      cout << "Unknown error" << endl;
149          }          }
150          return EXIT_FAILURE;          return EXIT_FAILURE;
151        } else if (!S_ISDIR(buf.st_mode)) {
152            cout << "Unable to open DESTDIR: Is not a directory." << endl;
153            return EXIT_FAILURE;
154        } else if (!(S_IWUSR & buf.st_mode) || !(S_IXUSR & buf.st_mode)) {
155            cout << "Unable to open DESTDIR: Permission denied." << endl;
156            return EXIT_FAILURE;
157      }      }
     if (dir) closedir(dir);  
158      try {      try {
159          RIFF::File* riff = new RIFF::File(argv[1]);          RIFF::File* riff = new RIFF::File(argv[1]);
160          gig::File*  gig  = new gig::File(riff);          gig::File*  gig  = new gig::File(riff);
# Line 161  int main(int argc, char *argv[]) { Line 178  int main(int argc, char *argv[]) {
178  }  }
179    
180  void ExtractSamples(gig::File* gig, char* destdir, OrderMap* ordered) {  void ExtractSamples(gig::File* gig, char* destdir, OrderMap* ordered) {
181  #ifndef HAVE_SNDFILE  #if !HAVE_SNDFILE // use libaudiofile
182      hAFlib = NULL;      hAFlib = NULL;
183      openAFlib();      openAFlib();
184  #endif // !HAVE_SNDFILE  #endif // !HAVE_SNDFILE
185      uint8_t* pWave  = NULL;      uint8_t* pWave  = NULL;
186        int* pIntWave = NULL;
187      long BufferSize = 0;      long BufferSize = 0;
188      int samples     = 0;      int samples     = 0;
189        gig::buffer_t decompressionBuffer;
190        decompressionBuffer.Size = 0;
191      cout << "Seeking for available samples..." << flush;      cout << "Seeking for available samples..." << flush;
192      gig::Sample* pSample = gig->GetFirstSample();      gig::Sample* pSample = gig->GetFirstSample();
193      cout << "OK" << endl << flush;      cout << "OK" << endl << flush;
# Line 200  void ExtractSamples(gig::File* gig, char Line 220  void ExtractSamples(gig::File* gig, char
220    
221    
222  #if USE_DISK_STREAMING  #if USE_DISK_STREAMING
223          long neededsize = (pSample->Compressed) ? 10485760 /* 10 MB buffer */          long neededsize = pSample->BitDepth == 24 ?
224                                                  : pSample->SamplesTotal * pSample->FrameSize;              pSample->SamplesTotal * pSample->Channels * sizeof(int) :
225                pSample->SamplesTotal * pSample->FrameSize;
226          if (BufferSize < neededsize) {          if (BufferSize < neededsize) {
227              if (pWave) delete[] pWave;              if (pWave) delete[] pWave;
228              pWave = new uint8_t[neededsize];              pWave = new uint8_t[neededsize];
229              BufferSize = neededsize;              BufferSize = neededsize;
230          }          }
231            pIntWave = (int*)pWave;
232  #  if HASHED_READS_TEST  #  if HASHED_READS_TEST
233          unsigned long readsamples     = 0,          unsigned long readinthisrun   = 0,
                       readinthisrun   = 0,  
234                        samplepiecesize = 2000;                        samplepiecesize = 2000;
235          uint8_t* pSamplePiece = pWave;          uint8_t* pSamplePiece = pWave;
236          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
237              readinthisrun = pSample->Read(pSamplePiece, ++samplepiecesize);              readinthisrun = pSample->Read(pSamplePiece, ++samplepiecesize);
238              // 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;  
239          } while (readinthisrun == samplepiecesize);          } while (readinthisrun == samplepiecesize);
240    
         if (pSample->Compressed) { // hack  
             pSample->SamplesTotal = readsamples;  
             pSample->BitDepth = 16;  
         }  
241  #  else // read in one piece  #  else // read in one piece
242          if (pSample->Compressed) {          if (pSample->Compressed) {
243              pSample->SamplesTotal = pSample->Read(pWave, 10485760 >> 2); // assumes 16 bit stereo              if (decompressionBufferSize < pSample->SamplesTotal) {
244          }                  gig::Sample::DestroyDecompressionBuffer(decompressionBuffer);
245          else {                  decompressionBuffer = gig::Sample::CreateDecompressionBuffer(pSample->SamplesTotal);
246                    decompressionBufferSize = pSample->SamplesTotal;
247                }
248                pSample->Read(pWave, pSample->SamplesTotal, &decompressionBuffer);
249            } else {
250              pSample->Read(pWave, pSample->SamplesTotal);              pSample->Read(pWave, pSample->SamplesTotal);
251          }          }
252  #  endif // HASHED_READS_TEST  #  endif // HASHED_READS_TEST
253  #else // no disk streaming  #else // no disk streaming
254          if (pSample->Compressed) {          if (pSample->Compressed) {
255              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;
256            } else {
257                gig::buffer_t buffer = pSample->LoadSampleData(); // load wave into RAM
258                pWave = static_cast<uint8_t*>(buffer.pStart);
259                if (pSample->BitDepth == 24) {
260                    long neededsize = pSample->SamplesTotal * pSample->Channels;
261                    if (BufferSize < neededsize) {
262                        if (pIntWave) delete[] pIntWave;
263                        pIntWave = new int[neededsize];
264                        BufferSize = neededsize;
265                    }
266                }
267          }          }
         else pWave = (uint8_t*) pSample->LoadSampleData(); // load wave into RAM  
268  #endif // USE_DISK_STREAMING  #endif // USE_DISK_STREAMING
269          if (pWave) {          if (pWave) {
270    
271                // Both libsndfile and libaudiofile uses int for 24 bit
272                // samples. libgig however returns 3 bytes per sample, so
273                // we have to convert the wave data before writing.
274                if (pSample->BitDepth == 24) {
275                    int n = pSample->SamplesTotal * pSample->Channels;
276                    for (int i = n - 1 ; i >= 0 ; i--) {
277    #if HAVE_SNDFILE
278                        pIntWave[i] = pWave[i * 3] << 8 | pWave[i * 3 + 1] << 16 | pWave[i * 3 + 2] << 24;
279    #else
280                        pIntWave[i] = pWave[i * 3] | pWave[i * 3 + 1] << 8 | pWave[i * 3 + 2] << 16;
281    #endif
282                    }
283                }
284    
285              int res = writeWav(filename.c_str(),              int res = writeWav(filename.c_str(),
286                                 pWave,                                 pSample->BitDepth == 24 ? static_cast<void*>(pIntWave) : pWave,
287                                 pSample->SamplesTotal,                                 pSample->SamplesTotal,
288                                 pSample->Channels,                                 pSample->Channels,
289                                 pSample->BitDepth,                                 pSample->BitDepth,
# Line 252  void ExtractSamples(gig::File* gig, char Line 296  void ExtractSamples(gig::File* gig, char
296    
297          pSample = gig->GetNextSample();          pSample = gig->GetNextSample();
298      }      }
299      if (pWave) delete[] (uint8_t*) pWave;      gig::Sample::DestroyDecompressionBuffer(decompressionBuffer);
300  #ifndef HAVE_SNDFILE  #if USE_DISK_STREAMING
301        if (pWave) delete[] pWave;
302    #else
303        if (pIntWave) delete[] pIntWave;
304    #endif
305    #if !HAVE_SNDFILE // use libaudiofile
306      closeAFlib();      closeAFlib();
307  #endif // !HAVE_SNDFILE  #endif // !HAVE_SNDFILE
308  }  }
# Line 266  int writeWav(const char* filename, void* Line 315  int writeWav(const char* filename, void*
315      switch (bitdepth) {      switch (bitdepth) {
316          case 8:          case 8:
317              format |= SF_FORMAT_PCM_S8;              format |= SF_FORMAT_PCM_S8;
             cout << "8 bit" << endl << flush;  
318              break;              break;
319          case 16:          case 16:
320              format |= SF_FORMAT_PCM_16;              format |= SF_FORMAT_PCM_16;
             cout << "16 bit" << endl << flush;  
321              break;              break;
322          case 24:          case 24:
323              format |= SF_FORMAT_PCM_24;              format |= SF_FORMAT_PCM_24;
             cout << "24 bit" << endl << flush;  
324              break;              break;
325          case 32:          case 32:
326              format |= SF_FORMAT_PCM_32;              format |= SF_FORMAT_PCM_32;
             cout << "32 bit" << endl << flush;  
327              break;              break;
328          default:          default:
329              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 293  int writeWav(const char* filename, void* Line 338  int writeWav(const char* filename, void*
338          cerr << "Error: Unable to open output file \'" << filename << "\'.\n" << flush;          cerr << "Error: Unable to open output file \'" << filename << "\'.\n" << flush;
339          return -1;          return -1;
340      }      }
341      if (sf_write_short(hfile, (short*)samples, channels * samplecount) != channels * samplecount) {      sf_count_t res = bitdepth == 24 ?
342            sf_write_int(hfile, static_cast<int*>(samples), channels * samplecount) :
343            sf_write_short(hfile, static_cast<short*>(samples), channels * samplecount);
344        if (res != channels * samplecount) {
345          cerr << sf_strerror(hfile) << endl << flush;          cerr << sf_strerror(hfile) << endl << flush;
346          sf_close(hfile);          sf_close(hfile);
347          return -1;          return -1;
348      }      }
349      sf_close(hfile);      sf_close(hfile);
350  #else  #else // use libaudiofile
351      AFfilesetup setup = _afNewFileSetup();      AFfilesetup setup = _afNewFileSetup();
352      _afInitFileFormat(setup, AF_FILE_WAVE);      _afInitFileFormat(setup, AF_FILE_WAVE);
353      _afInitChannels(setup, AF_DEFAULT_TRACK, channels);      _afInitChannels(setup, AF_DEFAULT_TRACK, channels);
# Line 316  int writeWav(const char* filename, void* Line 364  int writeWav(const char* filename, void*
364      return 0; // success      return 0; // success
365  }  }
366    
367  #ifndef HAVE_SNDFILE  #if !HAVE_SNDFILE // use libaudiofile
368  void openAFlib() {  void openAFlib() {
369      hAFlib = dlopen("libaudiofile.so", RTLD_NOW);      hAFlib = dlopen("libaudiofile.so", RTLD_NOW);
370      if (!hAFlib) {      if (!hAFlib) {
# Line 341  void closeAFlib() { Line 389  void closeAFlib() {
389  #endif // !HAVE_SNDFILE  #endif // !HAVE_SNDFILE
390    
391  string Revision() {  string Revision() {
392      string s = "$Revision: 1.6 $";      string s = "$Revision: 1.12 $";
393      return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword      return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
394  }  }
395    
# Line 352  void PrintVersion() { Line 400  void PrintVersion() {
400      char versionBuffer[128];      char versionBuffer[128];
401      sf_command(NULL, SFC_GET_LIB_VERSION, versionBuffer, 128);      sf_command(NULL, SFC_GET_LIB_VERSION, versionBuffer, 128);
402      cout << ", " << versionBuffer;      cout << ", " << versionBuffer;
403      #endif // HAVE_SNDFILE      #else // use libaudiofile
404      cout << endl;      cout << "\nbuilt against libaudiofile "
405      #if !HAVE_SNDFILE           << LIBAUDIOFILE_MAJOR_VERSION << "." << LIBAUDIOFILE_MINOR_VERSION;
     cout << "built against libaudiofile "  
          << LIBAUDIOFILE_MAJOR_VERSION << "." << LIBAUDIOFILE_MINOR_VERSION  
406      # ifdef LIBAUDIOFILE_MICRO_VERSION      # ifdef LIBAUDIOFILE_MICRO_VERSION
407           << "." << LIBAUDIOFILE_MICRO_VERSION      cout << "." << LIBAUDIOFILE_MICRO_VERSION;
408      # endif // LIBAUDIOFILE_MICRO_VERSION      # endif // LIBAUDIOFILE_MICRO_VERSION
409           << endl;      #endif // HAVE_SNDFILE
410      #endif // !HAVE_SNDFILE      cout << endl;
411  }  }
412    
413  void PrintUsage() {  void PrintUsage() {

Legend:
Removed from v.549  
changed lines
  Added in v.1953

  ViewVC Help
Powered by ViewVC