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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3442 - (show annotations) (download)
Sat Dec 22 18:59:29 2018 UTC (5 years, 3 months ago) by schoenebeck
File size: 29613 byte(s)
* GIG FORMAT EXTENSION: Added attribute
  DimensionRegion::SustainReleaseTrigger which allows to define whether
  a sustain pedal up event shall cause a release trigger sample to be
  played (default: don't play release trigger sample by sustain pedal).
* Bumped version (4.1.0.svn7).

1 /***************************************************************************
2 * *
3 * libgig - C++ cross-platform Gigasampler format file access library *
4 * *
5 * Copyright (C) 2003-2018 by Christian Schoenebeck *
6 * <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 *
11 * 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 *
13 * (at your option) any later version. *
14 * *
15 * This program is distributed in the hope that it will be useful, *
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
18 * GNU General Public License for more details. *
19 * *
20 * You should have received a copy of the GNU General Public License *
21 * along with this program; if not, write to the Free Software *
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, *
23 * MA 02111-1307 USA *
24 ***************************************************************************/
25
26 #ifdef HAVE_CONFIG_H
27 # include <config.h>
28 #endif
29
30 #include <iostream>
31 #include <cstdlib>
32 #include <string>
33
34 #include "../gig.h"
35
36 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);
43 void PrintScripts(gig::File* gig);
44 void PrintInstruments(gig::File* gig);
45 void PrintInstrumentNamesOnly(gig::File* gig);
46 void PrintRegions(gig::Instrument* instr);
47 void PrintUsage();
48 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[])
65 {
66 bool bVerify = false;
67 bool bRebuildChecksums = false;
68 bool bInstrumentNamesOnly = false;
69
70 if (argc <= 1) {
71 PrintUsage();
72 return EXIT_FAILURE;
73 }
74
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) {
108 cout << "Invalid file argument!" << endl;
109 return EXIT_FAILURE;
110 }
111 fclose(hFile);
112 try {
113 RIFF::File* riff = new RIFF::File(filename);
114 gig::File* gig = new gig::File(riff);
115
116 if (bRebuildChecksums) {
117 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;
138 delete riff;
139 }
140 catch (RIFF::Exception e) {
141 e.PrintMessage();
142 return EXIT_FAILURE;
143 }
144 catch (...) {
145 cout << "Unknown exception while trying to parse file." << endl;
146 return EXIT_FAILURE;
147 }
148
149 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) {
211 int samples = 0;
212 cout << "ALL Available Samples (as there might be more than referenced by Instruments):" << endl;
213 PubSample* pSample = (PubSample*) gig->GetFirstSample();
214 while (pSample) {
215 samples++;
216 // determine sample's name
217 string name = pSample->pInfo->Name;
218 if (name == "") name = "<NO NAME>";
219 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 << ", ";
227 cout << "Group " << iGroup << ", ";
228 cout << pSample->SamplesPerSecond << "Hz, " << pSample->Channels << " Channels, " << pSample->Loops << " Loops";
229 if (pSample->Loops) {
230 cout << " (Type: ";
231 switch (pSample->LoopType) {
232 case gig::loop_type_normal: cout << "normal)"; break;
233 case gig::loop_type_bidirectional: cout << "pingpong)"; break;
234 case gig::loop_type_backward: cout << "reverse)"; break;
235 }
236 cout << ", LoopFraction=" << pSample->LoopFraction << ", Start=" << pSample->LoopStart << ", End=" << pSample->LoopEnd;
237 cout << ", LoopPlayCount=" << pSample->LoopPlayCount;
238 }
239 cout << flush;
240 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
279 void PrintInstruments(gig::File* gig) {
280 int instruments = 0;
281 cout << "Available Instruments:" << endl;
282 gig::Instrument* pInstrument = gig->GetFirstInstrument();
283 while (pInstrument) {
284 instruments++;
285 string name = pInstrument->pInfo->Name;
286 if (name == "") name = "<NO NAME>";
287 else name = '\"' + name + '\"';
288 cout << " Instrument " << instruments << ") " << name << ", ";
289
290 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);
300
301 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) {
318 int iRegion = 1;
319 gig::Region* pRegion = instr->GetFirstRegion();
320 while (pRegion) {
321 cout << " Region " << iRegion++ << ") ";
322 gig::Sample* pSample = pRegion->GetSample();
323 if (pSample) {
324 cout << "Sample: ";
325 if (pSample->pInfo->Name != "") {
326 cout << "\"" << pSample->pInfo->Name << "\", ";
327 }
328 cout << pSample->SamplesPerSecond << "Hz, " << endl;
329 }
330 else {
331 cout << "<NO_VALID_SAMPLE_REFERENCE> ";
332 }
333 cout << " KeyRange=" << pRegion->KeyRange.low << "-" << pRegion->KeyRange.high << ", ";
334 cout << "VelocityRange=" << pRegion->VelocityRange.low << "-" << pRegion->VelocityRange.high << ", Layers=" << pRegion->Layers << endl;
335 cout << " Loops=" << pRegion->SampleLoops << endl;
336 cout << " Dimensions=" << pRegion->Dimensions << endl;
337 for (int iDimension = 0; iDimension < pRegion->Dimensions; iDimension++) {
338 cout << " Dimension[" << iDimension << "]: Type=";
339 gig::dimension_def_t DimensionDef = pRegion->pDimensionDefinitions[iDimension];
340 switch (DimensionDef.dimension) {
341 case gig::dimension_none:
342 cout << "NONE";
343 break;
344 case gig::dimension_samplechannel: // If used sample has more than one channel (thus is not mono).
345 cout << "SAMPLECHANNEL";
346 break;
347 case gig::dimension_layer: { // For layering of up to 8 instruments (and eventually crossfading of 2 or 4 layers).
348 gig::crossfade_t crossfade = pRegion->pDimensionRegions[iDimension]->Crossfade;
349 cout << "LAYER (Crossfade in_start=" << (int) crossfade.in_start << ",in_end=" << (int) crossfade.in_end << ",out_start=" << (int) crossfade.out_start << ",out_end=" << (int) crossfade.out_end << ")";
350 break;
351 }
352 case gig::dimension_velocity: // Key Velocity (this is the only dimension where the ranges can exactly be defined).
353 cout << "VELOCITY";
354 break;
355 case gig::dimension_channelaftertouch: // Channel Key Pressure
356 cout << "AFTERTOUCH";
357 break;
358 case gig::dimension_releasetrigger: // Special dimension for triggering samples on releasing a key.
359 cout << "RELEASETRIGGER";
360 break;
361 case gig::dimension_keyboard: // Key Position
362 cout << "KEYBOARD";
363 break;
364 case gig::dimension_roundrobin: // Different samples triggered each time a note is played, dimension regions selected in sequence
365 cout << "ROUNDROBIN";
366 break;
367 case gig::dimension_random: // Different samples triggered each time a note is played, random order
368 cout << "RANDOM";
369 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)
377 cout << "MODWHEEL";
378 break;
379 case gig::dimension_breath: // Breath Controller (Coarse, MIDI Controller 2)
380 cout << "BREATH";
381 break;
382 case gig::dimension_foot: // Foot Pedal (Coarse, MIDI Controller 4)
383 cout << "FOOT";
384 break;
385 case gig::dimension_portamentotime: // Portamento Time (Coarse, MIDI Controller 5)
386 cout << "PORTAMENTOTIME";
387 break;
388 case gig::dimension_effect1: // Effect Controller 1 (Coarse, MIDI Controller 12)
389 cout << "EFFECT1";
390 break;
391 case gig::dimension_effect2: // Effect Controller 2 (Coarse, MIDI Controller 13)
392 cout << "EFFECT2";
393 break;
394 case gig::dimension_genpurpose1: // General Purpose Controller 1 (Slider, MIDI Controller 16)
395 cout << "GENPURPOSE1";
396 break;
397 case gig::dimension_genpurpose2: // General Purpose Controller 2 (Slider, MIDI Controller 17)
398 cout << "GENPURPOSE2";
399 break;
400 case gig::dimension_genpurpose3: // General Purpose Controller 3 (Slider, MIDI Controller 18)
401 cout << "GENPURPOSE3";
402 break;
403 case gig::dimension_genpurpose4: // General Purpose Controller 4 (Slider, MIDI Controller 19)
404 cout << "GENPURPOSE4";
405 break;
406 case gig::dimension_sustainpedal: // Sustain Pedal (MIDI Controller 64)
407 cout << "SUSTAINPEDAL";
408 break;
409 case gig::dimension_portamento: // Portamento (MIDI Controller 65)
410 cout << "PORTAMENTO";
411 break;
412 case gig::dimension_sostenutopedal: // Sostenuto Pedal (MIDI Controller 66)
413 cout << "SOSTENUTOPEDAL";
414 break;
415 case gig::dimension_softpedal: // Soft Pedal (MIDI Controller 67)
416 cout << "SOFTPEDAL";
417 break;
418 case gig::dimension_genpurpose5: // General Purpose Controller 5 (Button, MIDI Controller 80)
419 cout << "GENPURPOSE5";
420 break;
421 case gig::dimension_genpurpose6: // General Purpose Controller 6 (Button, MIDI Controller 81)
422 cout << "GENPURPOSE6";
423 break;
424 case gig::dimension_genpurpose7: // General Purpose Controller 7 (Button, MIDI Controller 82)
425 cout << "GENPURPOSE7";
426 break;
427 case gig::dimension_genpurpose8: // General Purpose Controller 8 (Button, MIDI Controller 83)
428 cout << "GENPURPOSE8";
429 break;
430 case gig::dimension_effect1depth: // Effect 1 Depth (MIDI Controller 91)
431 cout << "EFFECT1DEPTH";
432 break;
433 case gig::dimension_effect2depth: // Effect 2 Depth (MIDI Controller 92)
434 cout << "EFFECT2DEPTH";
435 break;
436 case gig::dimension_effect3depth: // Effect 3 Depth (MIDI Controller 93)
437 cout << "EFFECT3DEPTH";
438 break;
439 case gig::dimension_effect4depth: // Effect 4 Depth (MIDI Controller 94)
440 cout << "EFFECT4DEPTH";
441 break;
442 case gig::dimension_effect5depth: // Effect 5 Depth (MIDI Controller 95)
443 cout << "EFFECT5DEPTH";
444 break;
445 default:
446 cout << "UNKNOWN (" << int(DimensionDef.dimension) << ") - please report this !";
447 break;
448 }
449 cout << ", Bits=" << (uint) DimensionDef.bits << ", Zones=" << (uint) DimensionDef.zones;
450 cout << ", SplitType=";
451 switch (DimensionDef.split_type) {
452 case gig::split_type_normal:
453 cout << "NORMAL" << endl;
454 break;
455 case gig::split_type_bit:
456 cout << "BIT" << endl;
457 break;
458 default:
459 cout << "UNKNOWN" << endl;
460 }
461 }
462
463 PrintDimensionRegions(pRegion);
464
465 pRegion = instr->GetNextRegion();
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) {
479 int dimensionRegions = 0;
480 gig::DimensionRegion* pDimensionRegion;
481 while (dimensionRegions < rgn->DimensionRegions) {
482 pDimensionRegion = rgn->pDimensionRegions[dimensionRegions];
483 if (!pDimensionRegion) break;
484
485 cout << " Dimension Region " << dimensionRegions + 1 << ")" << endl;
486
487 gig::Sample* pSample = pDimensionRegion->pSample;
488 if (pSample) {
489 cout << " Sample: ";
490 if (pSample->pInfo->Name != "") {
491 cout << "\"" << pSample->pInfo->Name << "\", ";
492 }
493 cout << pSample->SamplesPerSecond << "Hz, ";
494 cout << "UnityNote=" << (int) pDimensionRegion->UnityNote << ", FineTune=" << (int) pDimensionRegion->FineTune << ", Gain=" << (-pDimensionRegion->Gain / 655360.0) << "dB, SampleStartOffset=" << pDimensionRegion->SampleStartOffset << endl;
495 }
496 else {
497 cout << " Sample: <NO_VALID_SAMPLE_REFERENCE> " << endl;
498 }
499 cout << " LFO1Frequency=" << pDimensionRegion->LFO1Frequency << "Hz, LFO1InternalDepth=" << pDimensionRegion-> LFO1InternalDepth << ", LFO1ControlDepth=" << pDimensionRegion->LFO1ControlDepth << " LFO1Controller=" << pDimensionRegion->LFO1Controller << endl;
500 cout << " LFO2Frequency=" << pDimensionRegion->LFO2Frequency << "Hz, LFO2InternalDepth=" << pDimensionRegion-> LFO2InternalDepth << ", LFO2ControlDepth=" << pDimensionRegion->LFO2ControlDepth << " LFO2Controller=" << pDimensionRegion->LFO2Controller << endl;
501 cout << " LFO3Frequency=" << pDimensionRegion->LFO3Frequency << "Hz, LFO3InternalDepth=" << pDimensionRegion-> LFO3InternalDepth << ", LFO3ControlDepth=" << pDimensionRegion->LFO3ControlDepth << " LFO3Controller=" << pDimensionRegion->LFO3Controller << endl;
502 cout << " EG1PreAttack=" << pDimensionRegion->EG1PreAttack << "permille, EG1Attack=" << pDimensionRegion->EG1Attack << "s, EG1Decay1=" << pDimensionRegion->EG1Decay1 << "s, EG1Sustain=" << pDimensionRegion->EG1Sustain << "permille, EG1Release=" << pDimensionRegion->EG1Release << "s, EG1Decay2=" << pDimensionRegion->EG1Decay2 << "s, EG1Hold=" << pDimensionRegion->EG1Hold << endl;
503 cout << " EG2PreAttack=" << pDimensionRegion->EG2PreAttack << "permille, EG2Attack=" << pDimensionRegion->EG2Attack << "s, EG2Decay1=" << pDimensionRegion->EG2Decay1 << "s, EG2Sustain=" << pDimensionRegion->EG2Sustain << "permille, EG2Release=" << pDimensionRegion->EG2Release << "s, EG2Decay2=" << pDimensionRegion->EG2Decay2 << "s" << endl;
504 cout << " VCFEnabled=" << pDimensionRegion->VCFEnabled << ", VCFType=" << pDimensionRegion->VCFType << ", VCFCutoff=" << (int) pDimensionRegion->VCFCutoff << ", VCFResonance=" << (int) pDimensionRegion->VCFResonance << ", VCFCutoffController=" << pDimensionRegion->VCFCutoffController << endl;
505 cout << " VelocityResponseCurve=";
506 switch (pDimensionRegion->VelocityResponseCurve) {
507 case gig::curve_type_nonlinear:
508 cout << "NONLINEAR";
509 break;
510 case gig::curve_type_linear:
511 cout << "LINEAR";
512 break;
513 case gig::curve_type_special:
514 cout << "SPECIAL";
515 break;
516 case gig::curve_type_unknown:
517 default:
518 cout << "UNKNOWN - please report this !";
519 }
520 cout << ", VelocityResponseDepth=" << (int) pDimensionRegion->VelocityResponseDepth << ", VelocityResponseCurveScaling=" << (int) pDimensionRegion->VelocityResponseCurveScaling << endl;
521 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++;
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() {
631 cout << "gigdump - parses Gigasampler files and prints out the content." << endl;
632 cout << endl;
633 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 }

Properties

Name Value
svn:keywords Revision

  ViewVC Help
Powered by ViewVC