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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (hide annotations) (download)
Sat Oct 25 20:15:04 2003 UTC (20 years, 5 months ago) by schoenebeck
File size: 12026 byte(s)
Initial revision

1 schoenebeck 2 /***************************************************************************
2     * *
3     * libgig - C++ cross-platform Gigasampler format file loader library *
4     * *
5     * Copyright (C) 2003 by Christian Schoenebeck *
6     * <cuse@users.sourceforge.net> *
7     * *
8     * 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 *
10     * the Free Software Foundation; either version 2 of the License, or *
11     * (at your option) any later version. *
12     * *
13     * This program is distributed in the hope that it will be useful, *
14     * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16     * GNU General Public License for more details. *
17     * *
18     * You should have received a copy of the GNU General Public License *
19     * along with this program; if not, write to the Free Software *
20     * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
21     * MA 02111-1307 USA *
22     ***************************************************************************/
23    
24     #ifdef HAVE_CONFIG_H
25     #include <config.h>
26     #endif
27    
28     // just for testing the disk streaming capability of libgig;
29     // you will also need to set this to 1 at the moment if you want to
30     // extract compressed samples, as I haven't implemented the
31     // decompression algorithm in gig::Sample::LoadSampleData() yet
32     #define USE_DISK_STREAMING 1
33    
34     // only when USE_DISK_STREAMING is set to 1:
35     // just for testing the disk stream capability; with this option set
36     // gigextract will read the samples in smaller pieces, just to stress
37     // gig::Sample::Read() method a bit
38     #define HASHED_READS_TEST 1
39    
40     #include <iostream>
41     #include <cstdlib>
42     #include <stdlib.h>
43     #include <sys/types.h>
44     #include <sys/stat.h>
45     #include <dirent.h>
46     #include <errno.h>
47     #include <dlfcn.h>
48     #include <audiofile.h>
49     #include "gig.h"
50    
51     using namespace std;
52    
53     typedef map<unsigned int, bool> OrderMap;
54     OrderMap* pOrderedSamples = NULL;
55    
56     void PrintUsage();
57     void ExtractSamples(gig::File* gig, char* destdir, OrderMap* ordered);
58     int writeWav(const char* filename, void* samples, long samplecount, int channels, int bitdepth, long rate);
59     void* hAFlib; // handle to libaudiofile
60     void openAFlib(void);
61     void closeAFlib(void);
62     // pointers to libaudiofile functions
63     AFfilesetup(*_afNewFileSetup)(void);
64     void(*_afFreeFileSetup)(AFfilesetup);
65     void(*_afInitChannels)(AFfilesetup,int,int);
66     void(*_afInitSampleFormat)(AFfilesetup,int,int,int);
67     void(*_afInitFileFormat)(AFfilesetup,int);
68     void(*_afInitRate)(AFfilesetup,int,double);
69     int(*_afWriteFrames)(AFfilehandle,int,const void*,int);
70     AFfilehandle(*_afOpenFile)(const char*,const char*,AFfilesetup);
71     int(*_afCloseFile)(AFfilehandle file);
72     string ToString(int i);
73    
74     int main(int argc, char *argv[]) {
75     if (argc < 3) {
76     PrintUsage();
77     return EXIT_FAILURE;
78     }
79     if (argc > 3) { // extracting specific samples
80     pOrderedSamples = new OrderMap;
81     for (int i = 3; i < argc; i++) {
82     unsigned int index = atoi(argv[i]);
83     (*pOrderedSamples)[index] = true;
84     }
85     }
86     FILE* hFile = fopen(argv[1], "r");
87     if (!hFile) {
88     cout << "Invalid input file argument!" << endl;
89     return EXIT_FAILURE;
90     }
91     fclose(hFile);
92     DIR* dir = opendir(argv[2]);
93     if (!dir) {
94     cout << "Unable to open DESTDIR: ";
95     switch (errno) {
96     case EACCES: cout << "Permission denied." << endl;
97     break;
98     case EMFILE: cout << "Too many file descriptors in use by process." << endl;
99     break;
100     case ENFILE: cout << "Too many files are currently open in the system." << endl;
101     break;
102     case ENOENT: cout << "Directory does not exist, or name is an empty string." << endl;
103     break;
104     case ENOMEM: cout << "Insufficient memory to complete the operation." << endl;
105     break;
106     case ENOTDIR: cout << "Is not a directory." << endl;
107     break;
108     default: cout << "Unknown error" << endl;
109     }
110     return EXIT_FAILURE;
111     }
112     if (dir) closedir(dir);
113     try {
114     RIFF::File* riff = new RIFF::File(argv[1]);
115     gig::File* gig = new gig::File(riff);
116     cout << "Extracting samples from \"" << argv[1] << "\" to directory \"" << argv[2] << "\"." << endl << flush;
117     ExtractSamples(gig, argv[2], pOrderedSamples);
118     cout << "Extraction finished." << endl << flush;
119     delete gig;
120     delete riff;
121     if (pOrderedSamples) delete pOrderedSamples;
122     }
123     catch (RIFF::Exception e) {
124     e.PrintMessage();
125     return EXIT_FAILURE;
126     }
127     catch (...) {
128     cout << "Unknown exception while trying to parse file." << endl;
129     return EXIT_FAILURE;
130     }
131    
132     return EXIT_SUCCESS;
133     }
134    
135     void ExtractSamples(gig::File* gig, char* destdir, OrderMap* ordered) {
136     hAFlib = NULL;
137     openAFlib();
138     uint8_t* pWave = NULL;
139     long BufferSize = 0;
140     int samples = 0;
141     cout << "Seeking for available samples..." << flush;
142     gig::Sample* pSample = gig->GetFirstSample();
143     cout << "OK" << endl << flush;
144     while (pSample) {
145     samples++;
146     if (ordered) {
147     if ((*ordered)[samples] == false) {
148     pSample = gig->GetNextSample();
149     continue;
150     }
151     }
152     string name = pSample->pInfo->Name;
153     string filename = destdir;
154     if (filename[filename.size() - 1] != '/') filename += "/";
155     filename += ToString(samples);
156     filename += "_";
157     if (name == "") {
158     name = "(NO NAME)";
159     filename += "NONAME";
160     }
161     else {
162     filename += name;
163     name.insert(0, "\"");
164     name += "\"";
165     }
166     filename += ".wav";
167     if (pSample->Compressed) cout << "Decompressing ";
168     else cout << "Extracting ";
169     cout << "Sample " << samples << ") " << name << " (" << pSample->BitDepth <<"Bits, " << pSample->SamplesPerSecond << "Hz, " << pSample->Channels << " Channels, " << pSample->SamplesTotal << " Samples)..." << flush;
170    
171    
172     #if USE_DISK_STREAMING
173     if (pSample->Compressed) { // hack
174     pSample->BitDepth = 16;
175     pSample->FrameSize = 4;
176     }
177    
178     long neededsize = (pSample->Compressed) ? 10485760 /* 10 MB buffer */
179     : pSample->SamplesTotal * pSample->FrameSize;
180     if (BufferSize < neededsize) {
181     if (pWave) delete[] pWave;
182     pWave = new uint8_t[neededsize];
183     BufferSize = neededsize;
184     }
185     # if HASHED_READS_TEST
186     unsigned long readsamples = 0,
187     readinthisrun = 0,
188     samplepiecesize = 2000;
189     uint8_t* pSamplePiece = pWave;
190     do { // we read the sample in small pieces and increment the size with each run just to test streaming capability
191     readinthisrun = pSample->Read(pSamplePiece, ++samplepiecesize);
192     pSamplePiece += readinthisrun * pSample->FrameSize;
193     readsamples += readinthisrun;
194     } while (readinthisrun == samplepiecesize);
195    
196     if (pSample->Compressed) { // hack
197     pSample->SamplesTotal = readsamples;
198     }
199     # else // read in one piece
200     if (pSample->Compressed) {
201     pSample->SamplesTotal = pSample->Read(pWave, 10485760 >> 2); // assumes 16 bit stereo
202     }
203     else {
204     pSample->Read(pWave, pSample->SamplesTotal);
205     }
206     # endif // HASHED_READS_TEST
207     #else // no disk streaming
208     if (pSample->Compressed) {
209     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;
210     }
211     else pWave = (uint8_t*) pSample->LoadSampleData(); // load wave into RAM
212     #endif // USE_DISK_STREAMING
213     if (pWave) {
214     int res = writeWav(filename.c_str(),
215     pWave,
216     pSample->SamplesTotal,
217     pSample->Channels,
218     pSample->BitDepth,
219     pSample->SamplesPerSecond);
220     if (res < 0) cout << "Couldn't write sample data." << endl;
221     else cout << "ok" << endl;
222     pSample->ReleaseSampleData(); // free wave from RAM
223     }
224     else cout << "Failed to load sample data." << endl;
225    
226     pSample = gig->GetNextSample();
227     }
228     if (pWave) delete[] (uint8_t*) pWave;
229     closeAFlib();
230     }
231    
232     int writeWav(const char* filename, void* samples, long samplecount, int channels, int bitdepth, long rate) {
233     AFfilesetup setup = _afNewFileSetup();
234     _afInitFileFormat(setup, AF_FILE_WAVE);
235     _afInitChannels(setup, AF_DEFAULT_TRACK, channels);
236     _afInitSampleFormat(setup, AF_DEFAULT_TRACK, AF_SAMPFMT_TWOSCOMP, bitdepth);
237     _afInitRate(setup, AF_DEFAULT_TRACK, rate);
238     if (setup == AF_NULL_FILESETUP) return -1;
239     AFfilehandle hFile = _afOpenFile(filename, "w", setup);
240     if (hFile == AF_NULL_FILEHANDLE) return -1;
241     if (_afWriteFrames(hFile, AF_DEFAULT_TRACK, samples, samplecount) < 0) return -1;
242     _afCloseFile(hFile);
243     _afFreeFileSetup(setup);
244    
245     return 0;
246     }
247    
248     void openAFlib() {
249     hAFlib = dlopen("libaudiofile.so", RTLD_NOW);
250     if (!hAFlib) {
251     cout << "Unable to load library libaudiofile.so: " << dlerror() << endl;
252     return;
253     }
254     _afNewFileSetup = (AFfilesetup(*)(void)) dlsym(hAFlib, "afNewFileSetup");
255     _afFreeFileSetup = (void(*)(AFfilesetup)) dlsym(hAFlib, "afFreeFileSetup");
256     _afInitChannels = (void(*)(AFfilesetup,int,int)) dlsym(hAFlib, "afInitChannels");
257     _afInitSampleFormat = (void(*)(AFfilesetup,int,int,int)) dlsym(hAFlib, "afInitSampleFormat");
258     _afInitFileFormat = (void(*)(AFfilesetup,int)) dlsym(hAFlib, "afInitFileFormat");
259     _afInitRate = (void(*)(AFfilesetup,int,double)) dlsym(hAFlib, "afInitRate");
260     _afWriteFrames = (int(*)(AFfilehandle,int,const void*,int)) dlsym(hAFlib, "afWriteFrames");
261     _afOpenFile = (AFfilehandle(*)(const char*,const char*,AFfilesetup)) dlsym(hAFlib, "afOpenFile");
262     _afCloseFile = (int(*)(AFfilehandle file)) dlsym(hAFlib, "afCloseFile");
263     if (dlerror()) cout << "Failed to load function from libaudiofile.so: " << dlerror() << endl;
264     }
265    
266     void closeAFlib() {
267     if (hAFlib) dlclose(hAFlib);
268     }
269    
270     void PrintUsage() {
271     cout << "gigextract - extracts samples from a Gigasampler file." << endl;
272     cout << endl;
273     cout << "Usage: gigextract GIGFILE DESTDIR [SAMPLENR] [ [SAMPLENR] ...]" << endl;
274     cout << endl;
275     cout << " GIGFILE Input Gigasampler (.gig) file." << endl;
276     cout << endl;
277     cout << " DESTDIR Destination directory where all .wav files will be written to." << endl;
278     cout << endl;
279     cout << " SAMPLENR Index (/indices) of Sample(s) which should be extracted." << endl;
280     cout << " If no sample indices are given, all samples will be extracted" << endl;
281     cout << " (use gigdump to look for available samples)." << endl;
282     cout << endl;
283     }
284    
285     string ToString(int i) {
286     static char strbuf[1024];
287     sprintf(strbuf,"%d",i);
288     string s = strbuf;
289     return s;
290     }

  ViewVC Help
Powered by ViewVC