/[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 2 by schoenebeck, Sat Oct 25 20:15:04 2003 UTC revision 1063 by schoenebeck, Sat Mar 3 21:45:25 2007 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 by Christian Schoenebeck                           *   *   Copyright (C) 2003-2007 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  *
# Line 39  Line 41 
41    
42  #include <iostream>  #include <iostream>
43  #include <cstdlib>  #include <cstdlib>
44    #include <string.h>
45    #include <string>
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>
49  #include <dirent.h>  #include <dirent.h>
50  #include <errno.h>  #include <errno.h>
51  #include <dlfcn.h>  
 #include <audiofile.h>  
52  #include "gig.h"  #include "gig.h"
53    
54    #if POSIX
55    # include <dlfcn.h>
56    #endif
57    
58    // only libsndfile is available for Windows, so we use that for writing the sound files
59    #ifdef WIN32
60    # define HAVE_SNDFILE 1
61    #endif // WIN32
62    
63    // abort compilation here if neither libsndfile nor libaudiofile are available
64    #if !HAVE_SNDFILE && !HAVE_AUDIOFILE
65    # error "Neither libsndfile nor libaudiofile seem to be available!"
66    # error "(HAVE_SNDFILE and HAVE_AUDIOFILE are both false)"
67    #endif
68    
69    // we prefer libsndfile before libaudiofile
70    #if HAVE_SNDFILE
71    # include <sndfile.h>
72    #else
73    # include <audiofile.h>
74    #endif // HAVE_SNDFILE
75    
76  using namespace std;  using namespace std;
77    
78  typedef map<unsigned int, bool> OrderMap;  typedef map<unsigned int, bool> OrderMap;
79  OrderMap* pOrderedSamples = NULL;  OrderMap* pOrderedSamples = NULL;
80    
81    string Revision();
82    void PrintVersion();
83  void PrintUsage();  void PrintUsage();
84  void ExtractSamples(gig::File* gig, char* destdir, OrderMap* ordered);  void ExtractSamples(gig::File* gig, char* destdir, OrderMap* ordered);
85  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);
86    string ToString(int i);
87    
88    #if !HAVE_SNDFILE // use libaudiofile
89  void* hAFlib; // handle to libaudiofile  void* hAFlib; // handle to libaudiofile
90  void openAFlib(void);  void openAFlib(void);
91  void closeAFlib(void);  void closeAFlib(void);
# Line 69  void(*_afInitRate)(AFfilesetup,int,doubl Line 99  void(*_afInitRate)(AFfilesetup,int,doubl
99  int(*_afWriteFrames)(AFfilehandle,int,const void*,int);  int(*_afWriteFrames)(AFfilehandle,int,const void*,int);
100  AFfilehandle(*_afOpenFile)(const char*,const char*,AFfilesetup);  AFfilehandle(*_afOpenFile)(const char*,const char*,AFfilesetup);
101  int(*_afCloseFile)(AFfilehandle file);  int(*_afCloseFile)(AFfilehandle file);
102  string ToString(int i);  #endif // !HAVE_SNDFILE
103    
104  int main(int argc, char *argv[]) {  int main(int argc, char *argv[]) {
105         if (argc >= 2) {
106            if (argv[1][0] == '-') {
107                switch (argv[1][1]) {
108                    case 'v':
109                        PrintVersion();
110                        return EXIT_SUCCESS;
111                }
112            }
113        }
114      if (argc < 3) {      if (argc < 3) {
115          PrintUsage();          PrintUsage();
116          return EXIT_FAILURE;          return EXIT_FAILURE;
# Line 133  int main(int argc, char *argv[]) { Line 172  int main(int argc, char *argv[]) {
172  }  }
173    
174  void ExtractSamples(gig::File* gig, char* destdir, OrderMap* ordered) {  void ExtractSamples(gig::File* gig, char* destdir, OrderMap* ordered) {
175    #if !HAVE_SNDFILE // use libaudiofile
176      hAFlib = NULL;      hAFlib = NULL;
177      openAFlib();      openAFlib();
178    #endif // !HAVE_SNDFILE
179      uint8_t* pWave  = NULL;      uint8_t* pWave  = NULL;
180        int* pIntWave = NULL;
181      long BufferSize = 0;      long BufferSize = 0;
182      int samples     = 0;      int samples     = 0;
183        gig::buffer_t decompressionBuffer;
184        decompressionBuffer.Size = 0;
185        unsigned long decompressionBufferSize = 0;
186      cout << "Seeking for available samples..." << flush;      cout << "Seeking for available samples..." << flush;
187      gig::Sample* pSample = gig->GetFirstSample();      gig::Sample* pSample = gig->GetFirstSample();
188      cout << "OK" << endl << flush;      cout << "OK" << endl << flush;
# Line 170  void ExtractSamples(gig::File* gig, char Line 215  void ExtractSamples(gig::File* gig, char
215    
216    
217  #if USE_DISK_STREAMING  #if USE_DISK_STREAMING
218          if (pSample->Compressed) { // hack          long neededsize = pSample->BitDepth == 24 ?
219              pSample->BitDepth  = 16;              pSample->SamplesTotal * pSample->Channels * sizeof(int) :
220              pSample->FrameSize = 4;              pSample->SamplesTotal * pSample->FrameSize;
         }  
   
         long neededsize = (pSample->Compressed) ? 10485760 /* 10 MB buffer */  
                                                 : pSample->SamplesTotal * pSample->FrameSize;  
221          if (BufferSize < neededsize) {          if (BufferSize < neededsize) {
222              if (pWave) delete[] pWave;              if (pWave) delete[] pWave;
223              pWave = new uint8_t[neededsize];              pWave = new uint8_t[neededsize];
224              BufferSize = neededsize;              BufferSize = neededsize;
225          }          }
226            pIntWave = (int*)pWave;
227  #  if HASHED_READS_TEST  #  if HASHED_READS_TEST
228          unsigned long readsamples     = 0,          unsigned long readinthisrun   = 0,
                       readinthisrun   = 0,  
229                        samplepiecesize = 2000;                        samplepiecesize = 2000;
230          uint8_t* pSamplePiece = pWave;          uint8_t* pSamplePiece = pWave;
231          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
232              readinthisrun = pSample->Read(pSamplePiece, ++samplepiecesize);              readinthisrun = pSample->Read(pSamplePiece, ++samplepiecesize);
233              pSamplePiece += readinthisrun * pSample->FrameSize;              pSamplePiece += readinthisrun * pSample->FrameSize;
             readsamples  += readinthisrun;  
234          } while (readinthisrun == samplepiecesize);          } while (readinthisrun == samplepiecesize);
235    
         if (pSample->Compressed) { // hack  
             pSample->SamplesTotal = readsamples;  
         }  
236  #  else // read in one piece  #  else // read in one piece
237          if (pSample->Compressed) {          if (pSample->Compressed) {
238              pSample->SamplesTotal = pSample->Read(pWave, 10485760 >> 2); // assumes 16 bit stereo              if (decompressionBufferSize < pSample->SamplesTotal) {
239          }                  gig::Sample::DestroyDecompressionBuffer(decompressionBuffer);
240          else {                  decompressionBuffer = gig::Sample::CreateDecompressionBuffer(pSample->SamplesTotal);
241                    decompressionBufferSize = pSample->SamplesTotal;
242                }
243                pSample->Read(pWave, pSample->SamplesTotal, &decompressionBuffer);
244            } else {
245              pSample->Read(pWave, pSample->SamplesTotal);              pSample->Read(pWave, pSample->SamplesTotal);
246          }          }
247  #  endif // HASHED_READS_TEST  #  endif // HASHED_READS_TEST
248  #else // no disk streaming  #else // no disk streaming
249          if (pSample->Compressed) {          if (pSample->Compressed) {
250              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;
251            } else {
252                gig::buffer_t buffer = pSample->LoadSampleData(); // load wave into RAM
253                pWave = static_cast<uint8_t*>(buffer.pStart);
254                if (pSample->BitDepth == 24) {
255                    long neededsize = pSample->SamplesTotal * pSample->Channels;
256                    if (BufferSize < neededsize) {
257                        if (pIntWave) delete[] pIntWave;
258                        pIntWave = new int[neededsize];
259                        BufferSize = neededsize;
260                    }
261                }
262          }          }
         else pWave = (uint8_t*) pSample->LoadSampleData(); // load wave into RAM  
263  #endif // USE_DISK_STREAMING  #endif // USE_DISK_STREAMING
264          if (pWave) {          if (pWave) {
265    
266                // Both libsndfile and libaudiofile uses int for 24 bit
267                // samples. libgig however returns 3 bytes per sample, so
268                // we have to convert the wave data before writing.
269                if (pSample->BitDepth == 24) {
270                    int n = pSample->SamplesTotal * pSample->Channels;
271                    for (int i = n - 1 ; i >= 0 ; i--) {
272    #if HAVE_SNDFILE
273                        pIntWave[i] = pWave[i * 3] << 8 | pWave[i * 3 + 1] << 16 | pWave[i * 3 + 2] << 24;
274    #else
275                        pIntWave[i] = pWave[i * 3] | pWave[i * 3 + 1] << 8 | pWave[i * 3 + 2] << 16;
276    #endif
277                    }
278                }
279    
280              int res = writeWav(filename.c_str(),              int res = writeWav(filename.c_str(),
281                                 pWave,                                 pSample->BitDepth == 24 ? static_cast<void*>(pIntWave) : pWave,
282                                 pSample->SamplesTotal,                                 pSample->SamplesTotal,
283                                 pSample->Channels,                                 pSample->Channels,
284                                 pSample->BitDepth,                                 pSample->BitDepth,
# Line 225  void ExtractSamples(gig::File* gig, char Line 291  void ExtractSamples(gig::File* gig, char
291    
292          pSample = gig->GetNextSample();          pSample = gig->GetNextSample();
293      }      }
294      if (pWave) delete[] (uint8_t*) pWave;      gig::Sample::DestroyDecompressionBuffer(decompressionBuffer);
295    #if USE_DISK_STREAMING
296        if (pWave) delete[] pWave;
297    #else
298        if (pIntWave) delete[] pIntWave;
299    #endif
300    #if !HAVE_SNDFILE // use libaudiofile
301      closeAFlib();      closeAFlib();
302    #endif // !HAVE_SNDFILE
303  }  }
304    
305  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) {
306    #if HAVE_SNDFILE
307        SNDFILE* hfile;
308        SF_INFO  sfinfo;
309        int format = SF_FORMAT_WAV;
310        switch (bitdepth) {
311            case 8:
312                format |= SF_FORMAT_PCM_S8;
313                break;
314            case 16:
315                format |= SF_FORMAT_PCM_16;
316                break;
317            case 24:
318                format |= SF_FORMAT_PCM_24;
319                break;
320            case 32:
321                format |= SF_FORMAT_PCM_32;
322                break;
323            default:
324                cerr << "Error: Bithdepth " << ToString(bitdepth) << " not supported by libsndfile, ignoring sample!\n" << flush;
325                return -1;
326        }
327        memset(&sfinfo, 0, sizeof (sfinfo));
328        sfinfo.samplerate = rate;
329        sfinfo.frames     = samplecount;
330        sfinfo.channels   = channels;
331        sfinfo.format     = format;
332        if (!(hfile = sf_open(filename, SFM_WRITE, &sfinfo))) {
333            cerr << "Error: Unable to open output file \'" << filename << "\'.\n" << flush;
334            return -1;
335        }
336        sf_count_t res = bitdepth == 24 ?
337            sf_write_int(hfile, static_cast<int*>(samples), channels * samplecount) :
338            sf_write_short(hfile, static_cast<short*>(samples), channels * samplecount);
339        if (res != channels * samplecount) {
340            cerr << sf_strerror(hfile) << endl << flush;
341            sf_close(hfile);
342            return -1;
343        }
344        sf_close(hfile);
345    #else // use libaudiofile
346      AFfilesetup setup = _afNewFileSetup();      AFfilesetup setup = _afNewFileSetup();
347      _afInitFileFormat(setup, AF_FILE_WAVE);      _afInitFileFormat(setup, AF_FILE_WAVE);
348      _afInitChannels(setup, AF_DEFAULT_TRACK, channels);      _afInitChannels(setup, AF_DEFAULT_TRACK, channels);
# Line 241  int writeWav(const char* filename, void* Line 354  int writeWav(const char* filename, void*
354      if (_afWriteFrames(hFile, AF_DEFAULT_TRACK, samples, samplecount) < 0) return -1;      if (_afWriteFrames(hFile, AF_DEFAULT_TRACK, samples, samplecount) < 0) return -1;
355      _afCloseFile(hFile);      _afCloseFile(hFile);
356      _afFreeFileSetup(setup);      _afFreeFileSetup(setup);
357        #endif // HAVE_SNDFILE
358      return 0;  
359        return 0; // success
360  }  }
361    
362    #if !HAVE_SNDFILE // use libaudiofile
363  void openAFlib() {  void openAFlib() {
364      hAFlib = dlopen("libaudiofile.so", RTLD_NOW);      hAFlib = dlopen("libaudiofile.so", RTLD_NOW);
365      if (!hAFlib) {      if (!hAFlib) {
# Line 266  void openAFlib() { Line 381  void openAFlib() {
381  void closeAFlib() {  void closeAFlib() {
382      if (hAFlib) dlclose(hAFlib);      if (hAFlib) dlclose(hAFlib);
383  }  }
384    #endif // !HAVE_SNDFILE
385    
386    string Revision() {
387        string s = "$Revision: 1.10 $";
388        return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
389    }
390    
391    void PrintVersion() {
392        cout << "gigextract revision " << Revision() << endl;
393        cout << "using " << gig::libraryName() << " " << gig::libraryVersion();
394        #if HAVE_SNDFILE
395        char versionBuffer[128];
396        sf_command(NULL, SFC_GET_LIB_VERSION, versionBuffer, 128);
397        cout << ", " << versionBuffer;
398        #else // use libaudiofile
399        cout << "\nbuilt against libaudiofile "
400             << LIBAUDIOFILE_MAJOR_VERSION << "." << LIBAUDIOFILE_MINOR_VERSION;
401        # ifdef LIBAUDIOFILE_MICRO_VERSION
402        cout << "." << LIBAUDIOFILE_MICRO_VERSION;
403        # endif // LIBAUDIOFILE_MICRO_VERSION
404        #endif // HAVE_SNDFILE
405        cout << endl;
406    }
407    
408  void PrintUsage() {  void PrintUsage() {
409      cout << "gigextract - extracts samples from a Gigasampler file." << endl;      cout << "gigextract - extracts samples from a Gigasampler file." << endl;
410      cout << endl;      cout << endl;
411      cout << "Usage: gigextract GIGFILE DESTDIR [SAMPLENR] [ [SAMPLENR] ...]" << endl;      cout << "Usage: gigextract [-v] GIGFILE DESTDIR [SAMPLENR] [ [SAMPLENR] ...]" << endl;
412      cout << endl;      cout << endl;
413      cout << "   GIGFILE  Input Gigasampler (.gig) file." << endl;      cout << "   GIGFILE  Input Gigasampler (.gig) file." << endl;
414      cout << endl;      cout << endl;
# Line 280  void PrintUsage() { Line 418  void PrintUsage() {
418      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;
419      cout << "            (use gigdump to look for available samples)." << endl;      cout << "            (use gigdump to look for available samples)." << endl;
420      cout << endl;      cout << endl;
421        cout << "   -v       Print version and exit." << endl;
422        cout << endl;
423  }  }
424    
425  string ToString(int i) {  string ToString(int i) {

Legend:
Removed from v.2  
changed lines
  Added in v.1063

  ViewVC Help
Powered by ViewVC