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

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

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

libgig/trunk/src/gigdump.cpp revision 511 by schoenebeck, Thu May 5 13:49:53 2005 UTC libgig/trunk/src/tools/gigdump.cpp revision 3442 by schoenebeck, Sat Dec 22 18:59:29 2018 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-2018 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 27  Line 29 
29    
30  #include <iostream>  #include <iostream>
31  #include <cstdlib>  #include <cstdlib>
32    #include <string>
33    
34  #include "gig.h"  #include "../gig.h"
35    
36  using namespace std;  using namespace std;
37    
38    string Revision();
39    void PrintVersion();
40    void PrintFileInformation(gig::File* gig);
41    void PrintGroups(gig::File* gig);
42  void PrintSamples(gig::File* gig);  void PrintSamples(gig::File* gig);
43    void PrintScripts(gig::File* gig);
44  void PrintInstruments(gig::File* gig);  void PrintInstruments(gig::File* gig);
45    void PrintInstrumentNamesOnly(gig::File* gig);
46  void PrintRegions(gig::Instrument* instr);  void PrintRegions(gig::Instrument* instr);
47  void PrintUsage();  void PrintUsage();
48  void PrintDimensionRegions(gig::Region* rgn);  void PrintDimensionRegions(gig::Region* rgn);
49    bool VerifyFile(gig::File* gig);
50    void RebuildChecksumTable(gig::File* gig);
51    
52    class PubSample : public gig::Sample {
53    public:
54        using DLS::Sample::pCkData;
55    };
56    
57    class PubFile : public gig::File {
58    public:
59        using gig::File::VerifySampleChecksumTable;
60        using gig::File::RebuildSampleChecksumTable;
61    };
62    
63    
64  int main(int argc, char *argv[])  int main(int argc, char *argv[])
65  {  {
66        bool bVerify = false;
67        bool bRebuildChecksums = false;
68        bool bInstrumentNamesOnly = false;
69    
70      if (argc <= 1) {      if (argc <= 1) {
71          PrintUsage();          PrintUsage();
72          return EXIT_FAILURE;          return EXIT_FAILURE;
73      }      }
74      FILE* hFile = fopen(argv[1], "r");  
75        int iArg;
76        for (iArg = 1; iArg < argc; ++iArg) {
77            const string opt = argv[iArg];
78            if (opt == "--") { // common for all command line tools: separator between initial option arguments and i.e. subsequent file arguments
79                iArg++;
80                break;
81            }
82            if (opt.substr(0, 1) != "-") break;
83    
84            if (opt == "-v") {
85                PrintVersion();
86                return EXIT_SUCCESS;
87            } else if (opt == "--verify") {
88                bVerify = true;
89            } else if (opt == "--rebuild-checksums") {
90                bRebuildChecksums = true;
91            } else if (opt == "--instrument-names") {
92                bInstrumentNamesOnly = true;
93            } else {
94                cerr << "Unknown option '" << opt << "'" << endl;
95                cerr << endl;
96                PrintUsage();
97                return EXIT_FAILURE;
98            }
99        }
100        if (iArg >= argc) {
101            cout << "No file name provided!" << endl;
102            return EXIT_FAILURE;
103        }
104        const char* filename = argv[iArg];
105    
106        FILE* hFile = fopen(filename, "r");
107      if (!hFile) {      if (!hFile) {
108          cout << "Invalid file argument!" << endl;          cout << "Invalid file argument!" << endl;
109          return EXIT_FAILURE;          return EXIT_FAILURE;
110      }      }
111      fclose(hFile);      fclose(hFile);
112      try {      try {
113          RIFF::File* riff = new RIFF::File(argv[1]);          RIFF::File* riff = new RIFF::File(filename);
114          gig::File*  gig  = new gig::File(riff);          gig::File*  gig  = new gig::File(riff);
115          PrintSamples(gig);  
116          cout << endl;          if (bRebuildChecksums) {
117          PrintInstruments(gig);              RebuildChecksumTable(gig);
118            } else if (bVerify) {
119                bool OK = VerifyFile(gig);
120                if (OK) cout << "All checks passed successfully! :-)\n";
121                return (OK) ? EXIT_SUCCESS : EXIT_FAILURE;
122            } else {
123                if (bInstrumentNamesOnly) {
124                    PrintInstrumentNamesOnly(gig);
125                } else {
126                    PrintFileInformation(gig);
127                    cout << endl;
128                    PrintGroups(gig);
129                    cout << endl;
130                    PrintSamples(gig);
131                    cout << endl;
132                    PrintScripts(gig);
133                    cout << endl;
134                    PrintInstruments(gig);
135                }
136            }
137          delete gig;          delete gig;
138          delete riff;          delete riff;
139      }      }
# Line 71  int main(int argc, char *argv[]) Line 149  int main(int argc, char *argv[])
149      return EXIT_SUCCESS;      return EXIT_SUCCESS;
150  }  }
151    
152    void PrintFileInformation(gig::File* gig) {
153        cout << "Global File Information:" << endl;
154        cout << "    Total instruments: " << gig->Instruments << endl;
155        if (gig->pVersion) {
156           cout << "    Version: " << gig->pVersion->major   << "."
157                               << gig->pVersion->minor   << "."
158                               << gig->pVersion->release << "."
159                               << gig->pVersion->build   << endl;
160        }
161        if (gig->pInfo) {
162            if (gig->pInfo->Name.size())
163                cout << "    Name: '" << gig->pInfo->Name << "'\n";
164            if (gig->pInfo->ArchivalLocation.size())
165                cout << "    ArchivalLocation: '" << gig->pInfo->ArchivalLocation << "'\n";
166            if (gig->pInfo->CreationDate.size())
167                cout << "    CreationDate: '" << gig->pInfo->CreationDate << "'\n";
168            if (gig->pInfo->Comments.size())
169                cout << "    Comments: '" << gig->pInfo->Comments << "'\n";
170            if (gig->pInfo->Product.size())
171                cout << "    Product: '" << gig->pInfo->Product << "'\n";
172            if (gig->pInfo->Copyright.size())
173                cout << "    Copyright: '" << gig->pInfo->Copyright << "'\n";
174            if (gig->pInfo->Artists.size())
175                cout << "    Artists: '" << gig->pInfo->Artists << "'\n";
176            if (gig->pInfo->Genre.size())
177                cout << "    Genre: '" << gig->pInfo->Genre << "'\n";
178            if (gig->pInfo->Keywords.size())
179                cout << "    Keywords: '" << gig->pInfo->Keywords << "'\n";
180            if (gig->pInfo->Engineer.size())
181                cout << "    Engineer: '" << gig->pInfo->Engineer << "'\n";
182            if (gig->pInfo->Technician.size())
183                cout << "    Technician: '" << gig->pInfo->Technician << "'\n";
184            if (gig->pInfo->Software.size())
185                cout << "    Software: '" << gig->pInfo->Software << "'\n";
186            if (gig->pInfo->Medium.size())
187                cout << "    Medium: '" << gig->pInfo->Medium << "'\n";
188            if (gig->pInfo->Source.size())
189                cout << "    Source: '" << gig->pInfo->Source << "'\n";
190            if (gig->pInfo->SourceForm.size())
191                cout << "    SourceForm: '" << gig->pInfo->SourceForm << "'\n";
192            if (gig->pInfo->Commissioned.size())
193                cout << "    Commissioned: '" << gig->pInfo->Commissioned << "'\n";
194        }
195    }
196    
197    void PrintGroups(gig::File* gig) {
198        int groups = 0;
199        cout << "ALL defined Groups:" << endl;
200        for (gig::Group* pGroup = gig->GetFirstGroup(); pGroup; pGroup = gig->GetNextGroup()) {
201            groups++;
202            string name = pGroup->Name;
203            if (name == "") name = "<NO NAME>";
204            else            name = '\"' + name + '\"';
205            cout << "    Group " << groups << ")" << endl;
206            cout << "        Name: " << name << endl;
207        }
208    }
209    
210  void PrintSamples(gig::File* gig) {  void PrintSamples(gig::File* gig) {
211      int samples = 0;      int samples = 0;
212      cout << "ALL Available Samples (as there might be more than referenced by Instruments):" << endl;      cout << "ALL Available Samples (as there might be more than referenced by Instruments):" << endl;
213      gig::Sample* pSample = gig->GetFirstSample();      PubSample* pSample = (PubSample*) gig->GetFirstSample();
214      while (pSample) {      while (pSample) {
215          samples++;          samples++;
216            // determine sample's name
217          string name = pSample->pInfo->Name;          string name = pSample->pInfo->Name;
218          if (name == "") name = "<NO NAME>";          if (name == "") name = "<NO NAME>";
219          else            name = '\"' + name + '\"';          else            name = '\"' + name + '\"';
220            // determine group this sample belongs to
221            int iGroup = 1;
222            for (gig::Group* pGroup = gig->GetFirstGroup(); pGroup; pGroup = gig->GetNextGroup(), iGroup++) {
223                if (pGroup == pSample->GetGroup()) break;
224            }
225            // print sample info
226          cout << "    Sample " << samples << ") " << name << ", ";          cout << "    Sample " << samples << ") " << name << ", ";
227            cout << "Group " << iGroup << ", ";
228          cout << pSample->SamplesPerSecond << "Hz, " << pSample->Channels << " Channels, " << pSample->Loops << " Loops";          cout << pSample->SamplesPerSecond << "Hz, " << pSample->Channels << " Channels, " << pSample->Loops << " Loops";
229          if (pSample->Loops) {          if (pSample->Loops) {
230              cout << " (Type: ";              cout << " (Type: ";
# Line 92  void PrintSamples(gig::File* gig) { Line 236  void PrintSamples(gig::File* gig) {
236              cout << ", LoopFraction=" << pSample->LoopFraction << ", Start=" << pSample->LoopStart << ", End=" << pSample->LoopEnd;              cout << ", LoopFraction=" << pSample->LoopFraction << ", Start=" << pSample->LoopStart << ", End=" << pSample->LoopEnd;
237              cout << ", LoopPlayCount=" << pSample->LoopPlayCount;              cout << ", LoopPlayCount=" << pSample->LoopPlayCount;
238          }          }
239          cout << ", Length=" << pSample->SamplesTotal << " Compressed=" << ((pSample->Compressed) ? "true" : "false") << endl;          cout << flush;
240          pSample = gig->GetNextSample();          printf(", crc=%x", pSample->GetWaveDataCRC32Checksum());
241            fflush(stdout);
242            cout << ", Length=" << pSample->SamplesTotal << " Compressed=" << ((pSample->Compressed) ? "true" : "false")
243                 << " foffset=" << pSample->pCkData->GetFilePos()
244                 << " fsz=" << pSample->pCkData->GetSize()
245                 << endl;
246    #if 0
247            {
248                const uint bufSize = 64;
249                unsigned char buf[bufSize] = {};
250                pSample->SetPos(0);
251                RIFF::file_offset_t n = pSample->pCkData->Read(&buf[0], bufSize, 1);
252                //RIFF::file_offset_t n = pSample->Read(&buf[0], bufSize / pSample->FrameSize);
253                cout << "        FrameSize=" << pSample->FrameSize << ",Data[" << n << "]" << flush;
254                for (int x = 0; x < bufSize; ++x)
255                    printf("%02x ", buf[x]);
256                printf("\n");
257                fflush(stdout);
258            }
259    #endif
260            pSample = (PubSample*) gig->GetNextSample();
261        }
262    }
263    
264    void PrintScripts(gig::File* gig) {
265        cout << "ALL Available Real-Time Instrument Scripts (as there might be more than referenced by Instruments):" << endl;
266        for (int g = 0; gig->GetScriptGroup(g); ++g) {
267            gig::ScriptGroup* pGroup = gig->GetScriptGroup(g);
268            cout << "    Group " << g+1 << ") '" << pGroup->Name << "'\n";
269            for (int s = 0; pGroup->GetScript(s); ++s) {
270                gig::Script* pScript = pGroup->GetScript(s);
271                cout << "        Script " << s+1 << ") '" << pScript->Name << "':\n";
272                cout << "[START OF SCRIPT]\n";
273                cout << pScript->GetScriptAsText();
274                cout << "[END OF SCRIPT]\n";
275            }
276      }      }
277  }  }
278    
# Line 109  void PrintInstruments(gig::File* gig) { Line 288  void PrintInstruments(gig::File* gig) {
288          cout << "    Instrument " << instruments << ") " << name << ", ";          cout << "    Instrument " << instruments << ") " << name << ", ";
289    
290          cout << " MIDIBank=" << pInstrument->MIDIBank << ", MIDIProgram=" << pInstrument->MIDIProgram << endl;          cout << " MIDIBank=" << pInstrument->MIDIBank << ", MIDIProgram=" << pInstrument->MIDIProgram << endl;
291    
292            cout << "        ScriptSlots=" << pInstrument->ScriptSlotCount() << endl;
293            for (int s = 0; s < pInstrument->ScriptSlotCount(); ++s) {
294                gig::Script* pScript = pInstrument->GetScriptOfSlot(s);
295                string name = pScript->Name;
296                cout << "        ScriptSlot[" << s << "]='" << name << "'\n";
297            }
298    
299          PrintRegions(pInstrument);          PrintRegions(pInstrument);
300    
301          pInstrument = gig->GetNextInstrument();          pInstrument = gig->GetNextInstrument();
302      }      }
303  }  }
304    
305    void PrintInstrumentNamesOnly(gig::File* gig) {
306        int instruments = 0;
307        gig::Instrument* pInstrument = gig->GetFirstInstrument();
308        for (; pInstrument; pInstrument = gig->GetNextInstrument()) {
309            instruments++;
310            string name = pInstrument->pInfo->Name;
311            if (name == "") name = "<NO NAME>";
312            else            name = '\"' + name + '\"';
313            cout << "Instrument " << instruments << ") " << name << endl;
314        }
315    }
316    
317  void PrintRegions(gig::Instrument* instr) {  void PrintRegions(gig::Instrument* instr) {
318      int iRegion = 1;      int iRegion = 1;
319      gig::Region* pRegion = instr->GetFirstRegion();      gig::Region* pRegion = instr->GetFirstRegion();
# Line 168  void PrintRegions(gig::Instrument* instr Line 367  void PrintRegions(gig::Instrument* instr
367                  case gig::dimension_random: // Different samples triggered each time a note is played, random order                  case gig::dimension_random: // Different samples triggered each time a note is played, random order
368                      cout << "RANDOM";                      cout << "RANDOM";
369                      break;                      break;
370                    case gig::dimension_smartmidi: // For MIDI tools like legato and repetition mode
371                        cout << "SMARTMIDI";
372                        break;
373                    case gig::dimension_roundrobinkeyboard: // Different samples triggered each time a note is played, any key advances the counter
374                        cout << "ROUNDROBINKEYBOARD";
375                        break;
376                  case gig::dimension_modwheel: // Modulation Wheel (MIDI Controller 1)                  case gig::dimension_modwheel: // Modulation Wheel (MIDI Controller 1)
377                      cout << "MODWHEEL";                      cout << "MODWHEEL";
378                      break;                      break;
# Line 247  void PrintRegions(gig::Instrument* instr Line 452  void PrintRegions(gig::Instrument* instr
452                  case gig::split_type_normal:                  case gig::split_type_normal:
453                      cout << "NORMAL" << endl;                      cout << "NORMAL" << endl;
454                      break;                      break;
                 case gig::split_type_customvelocity:  
                     cout << "CUSTOMVELOCITY" << endl;  
                     break;  
455                  case gig::split_type_bit:                  case gig::split_type_bit:
456                      cout << "BIT" << endl;                      cout << "BIT" << endl;
457                      break;                      break;
# Line 264  void PrintRegions(gig::Instrument* instr Line 466  void PrintRegions(gig::Instrument* instr
466      }      }
467  }  }
468    
469    template<typename T_int>
470    static void printIntArray(T_int* array, int size) {
471        printf("{");
472        for (int i = 0; i < size; ++i)
473            printf("[%d]=%d,", i, array[i]);
474        printf("}");
475        fflush(stdout);
476    }
477    
478  void PrintDimensionRegions(gig::Region* rgn) {  void PrintDimensionRegions(gig::Region* rgn) {
479      int dimensionRegions = 0;      int dimensionRegions = 0;
480      gig::DimensionRegion* pDimensionRegion;      gig::DimensionRegion* pDimensionRegion;
481      while (dimensionRegions < 32) {      while (dimensionRegions < rgn->DimensionRegions) {
482          pDimensionRegion = rgn->pDimensionRegions[dimensionRegions];          pDimensionRegion = rgn->pDimensionRegions[dimensionRegions];
483          if (!pDimensionRegion) break;          if (!pDimensionRegion) break;
484    
# Line 307  void PrintDimensionRegions(gig::Region* Line 518  void PrintDimensionRegions(gig::Region*
518                  cout << "UNKNOWN - please report this !";                  cout << "UNKNOWN - please report this !";
519          }          }
520          cout << ", VelocityResponseDepth=" << (int) pDimensionRegion->VelocityResponseDepth << ", VelocityResponseCurveScaling=" << (int) pDimensionRegion->VelocityResponseCurveScaling << endl;          cout << ", VelocityResponseDepth=" << (int) pDimensionRegion->VelocityResponseDepth << ", VelocityResponseCurveScaling=" << (int) pDimensionRegion->VelocityResponseCurveScaling << endl;
521          cout << "                Pan=" << (int) pDimensionRegion->Pan << endl;          cout << "                VelocityUpperLimit=" << (int) pDimensionRegion->VelocityUpperLimit << " DimensionUpperLimits[]=" << flush;
522            printIntArray(pDimensionRegion->DimensionUpperLimits, 8);
523            cout << endl;
524    #if 0 // requires access to protected member VelocityTable, so commented out for now
525            if (pDimensionRegion->VelocityTable) {
526                cout << "                VelocityTable[]=" << flush;
527                printIntArray(pDimensionRegion->VelocityTable, 127);
528                cout << endl;
529            }
530    #endif
531            cout << "                Pan=" << (int) pDimensionRegion->Pan;
532            cout << ", SustainReleaseTrigger=";
533            switch (pDimensionRegion->SustainReleaseTrigger) {
534                case gig::sust_rel_trg_none:
535                    cout << "NONE";
536                    break;
537                case gig::sust_rel_trg_maxvelocity:
538                    cout << "MAXVELOCITY";
539                    break;
540                case gig::sust_rel_trg_keyvelocity:
541                    cout << "KEYVELOCITY";
542                    break;
543            }
544            cout << endl;
545            {
546                gig::eg_opt_t& egopt = pDimensionRegion->EG1Options;
547                cout << "                EG1AttackCancel=" << egopt.AttackCancel << ", EG1AttackHoldCancel=" << egopt.AttackHoldCancel << ", EG1Decay1Cancel=" << egopt.Decay1Cancel << ", EG1Decay2Cancel=" << egopt.Decay2Cancel << ", EG1ReleaseCancel=" << egopt.ReleaseCancel << endl;
548            }
549            {
550                gig::eg_opt_t& egopt = pDimensionRegion->EG2Options;
551                cout << "                EG2AttackCancel=" << egopt.AttackCancel << ", EG2AttackHoldCancel=" << egopt.AttackHoldCancel << ", EG2Decay1Cancel=" << egopt.Decay1Cancel << ", EG2Decay2Cancel=" << egopt.Decay2Cancel << ", EG2ReleaseCancel=" << egopt.ReleaseCancel << endl;
552            }
553    
554          dimensionRegions++;          dimensionRegions++;
555      }      }
556  }  }
557    
558    struct _FailedSample {
559        gig::Sample* sample;
560        uint32_t calculatedCRC;
561    };
562    
563    bool VerifyFile(gig::File* _gig) {
564        PubFile* gig = (PubFile*) _gig;
565    
566        cout << "Verifying sample checksum table ... " << flush;
567        if (!gig->VerifySampleChecksumTable()) {
568            cout << "DAMAGED\n";
569            cout << "You may use --rebuild-checksums to repair the sample checksum table.\n";
570            return false;
571        }
572        cout << "OK\n" << flush;
573    
574        cout << "Verifying samples ... " << flush;
575        std::map<int,_FailedSample> failedSamples;
576        int iTotal = 0;
577        for (gig::Sample* pSample = gig->GetFirstSample(); pSample; pSample = gig->GetNextSample(), ++iTotal) {
578            uint32_t crc; // will be set to the actually now calculated checksum
579            if (!pSample->VerifyWaveData(&crc)) {
580                _FailedSample failed;
581                failed.sample = pSample;
582                failed.calculatedCRC = crc;
583                failedSamples[iTotal] = failed;
584            }
585        }
586        if (failedSamples.empty()) {
587            cout << "ALL OK\n";
588            return true;
589        } else {
590            cout << failedSamples.size() << " of " << iTotal << " Samples DAMAGED:\n";
591            for (std::map<int,_FailedSample>::iterator it = failedSamples.begin(); it != failedSamples.end(); ++it) {
592                const int i = it->first;
593                gig::Sample* pSample = it->second.sample;
594    
595                string name = pSample->pInfo->Name;
596                if (name == "") name = "<NO NAME>";
597                else            name = '\"' + name + '\"';
598    
599                cout << "Damaged Sample " << (i+1) << ") " << name << flush;
600                printf(" expectedCRC=%x calculatedCRC=%x\n", pSample->GetWaveDataCRC32Checksum(), it->second.calculatedCRC);
601            }
602            return false;
603        }
604    }
605    
606    void RebuildChecksumTable(gig::File* _gig) {
607        PubFile* gig = (PubFile*) _gig;
608    
609        cout << "Recalculating checksums of all samples ... " << flush;
610        bool bSaveRequired = gig->RebuildSampleChecksumTable();
611        cout << "OK\n";
612        if (bSaveRequired) {
613            cout << "WARNING: File structure change required, rebuilding entire file now ..." << endl;
614            gig->Save();
615            cout << "DONE\n";
616            cout << "NOTE: Since the entire file was rebuilt, you may need to manually check all samples in this particular case now!\n";
617        }
618    }
619    
620    string Revision() {
621        string s = "$Revision$";
622        return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
623    }
624    
625    void PrintVersion() {
626        cout << "gigdump revision " << Revision() << endl;
627        cout << "using " << gig::libraryName() << " " << gig::libraryVersion() << endl;
628    }
629    
630  void PrintUsage() {  void PrintUsage() {
631      cout << "gigdump - parses Gigasampler files and prints out the content." << endl;      cout << "gigdump - parses Gigasampler files and prints out the content." << endl;
632      cout << endl;      cout << endl;
633      cout << "Usage: gigdump FILE" << endl;      cout << "Usage: gigdump [-v | --verify | --rebuild-checksums] FILE" << endl;
634        cout << endl;
635        cout << "   --rebuild-checksums  Rebuild checksum table for all samples." << endl;
636        cout << endl;
637        cout << "   -v                   Print version and exit." << endl;
638        cout << endl;
639        cout << "   --verify             Checks raw wave data integrity of all samples." << endl;
640        cout << endl;
641        cout << "   --instrument-names   Print only instrument names." << endl;
642        cout << endl;
643  }  }

Legend:
Removed from v.511  
changed lines
  Added in v.3442

  ViewVC Help
Powered by ViewVC