1 |
/*************************************************************************** |
2 |
* * |
3 |
* libgig - C++ cross-platform Gigasampler format file access library * |
4 |
* * |
5 |
* Copyright (C) 2003-2009 by Christian Schoenebeck * |
6 |
* <cuse@users.sourceforge.net> * |
7 |
* Copyright (C) 2009 by Grigor Iliev <grigor@grigoriliev.com> * |
8 |
* * |
9 |
* This program is part of libsf2. * |
10 |
* * |
11 |
* This program is free software; you can redistribute it and/or modify * |
12 |
* it under the terms of the GNU General Public License as published by * |
13 |
* the Free Software Foundation; either version 2 of the License, or * |
14 |
* (at your option) any later version. * |
15 |
* * |
16 |
* This program is distributed in the hope that it will be useful, * |
17 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of * |
18 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * |
19 |
* GNU General Public License for more details. * |
20 |
* * |
21 |
* You should have received a copy of the GNU General Public License * |
22 |
* along with this program; if not, write to the Free Software * |
23 |
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, * |
24 |
* MA 02111-1307 USA * |
25 |
***************************************************************************/ |
26 |
|
27 |
#ifdef HAVE_CONFIG_H |
28 |
#include <config.h> |
29 |
#endif |
30 |
|
31 |
#include <iostream> |
32 |
#include <cstdlib> |
33 |
#include <string> |
34 |
#include <sstream> |
35 |
|
36 |
#include "SF.h" |
37 |
|
38 |
using namespace std; |
39 |
|
40 |
string Revision(); |
41 |
void PrintVersion(); |
42 |
void PrintSamples(sf2::File* sf); |
43 |
void PrintInstruments(sf2::File* sf); |
44 |
void PrintPeresets(sf2::File* sf); |
45 |
void PrintRegion(int idx, sf2::Region* reg); |
46 |
void PrintModulatorItem(sf2::ModulatorItem* mod); |
47 |
void PrintModulator(sf2::Modulator& mod); |
48 |
void PrintUsage(); |
49 |
void PrintSfInfo(sf2::File* sf); |
50 |
|
51 |
string GetControllerType(sf2::Modulator& mod); |
52 |
string GetControllerSource(sf2::Modulator& mod); |
53 |
string GetSampleType(uint16_t type); |
54 |
|
55 |
int main(int argc, char *argv[]) |
56 |
{ |
57 |
if (argc <= 1) { |
58 |
PrintUsage(); |
59 |
return EXIT_FAILURE; |
60 |
} |
61 |
if (argv[1][0] == '-') { |
62 |
switch (argv[1][1]) { |
63 |
case 'v': |
64 |
PrintVersion(); |
65 |
return EXIT_SUCCESS; |
66 |
} |
67 |
} |
68 |
FILE* hFile = fopen(argv[1], "r"); |
69 |
if (!hFile) { |
70 |
cout << "Invalid file argument!" << endl << endl; |
71 |
void PrintUsage(); |
72 |
return EXIT_FAILURE; |
73 |
} |
74 |
fclose(hFile); |
75 |
try { |
76 |
RIFF::File* riff = new RIFF::File(argv[1]); |
77 |
sf2::File* sf = new sf2::File(riff); |
78 |
PrintSfInfo(sf); |
79 |
PrintSamples(sf); |
80 |
cout << endl; |
81 |
PrintInstruments(sf); |
82 |
PrintPeresets(sf); |
83 |
delete sf; |
84 |
delete riff; |
85 |
} |
86 |
catch (RIFF::Exception e) { |
87 |
e.PrintMessage(); |
88 |
return EXIT_FAILURE; |
89 |
} |
90 |
catch (...) { |
91 |
cout << "Unknown exception while trying to parse file." << endl; |
92 |
return EXIT_FAILURE; |
93 |
} |
94 |
|
95 |
return EXIT_SUCCESS; |
96 |
} |
97 |
|
98 |
void PrintSfInfo(sf2::File* sf) { |
99 |
cout << "File info:" << endl; |
100 |
cout << "\tVersion: " << sf->pInfo->pVer->Major << "." << sf->pInfo->pVer->Minor << endl; |
101 |
cout << "\tBank Name: " << sf->pInfo->BankName << endl; |
102 |
cout << "\tSound Engine: " << sf->pInfo->SoundEngine << endl; |
103 |
cout << "\tSound ROM Name: " << sf->pInfo->RomName << endl; |
104 |
cout << "\tSound ROM Version: " << sf->pInfo->pRomVer->Major << "." << sf->pInfo->pRomVer->Minor << endl; |
105 |
cout << "\tCreation Date: " << sf->pInfo->CreationDate << endl; |
106 |
cout << "\tEngineers: " << sf->pInfo->Engineers << endl; |
107 |
cout << "\tProduct: " << sf->pInfo->Product << endl; |
108 |
cout << "\tCopyright: " << sf->pInfo->Copyright << endl; |
109 |
cout << "\tComments: " << sf->pInfo->Comments << endl; |
110 |
cout << "\tSoftware: " << sf->pInfo->Software << endl << endl; |
111 |
} |
112 |
|
113 |
void PrintSamples(sf2::File* sf) { |
114 |
cout << "Samples (" << sf->GetSampleCount() << "): " << endl; |
115 |
for (int i = 0; i < sf->GetSampleCount(); i++) { |
116 |
sf2::Sample* s = sf->GetSample(i); |
117 |
cout << "\t" << s->Name << " (" << "SampleRate: " << s->SampleRate; |
118 |
cout << ", Pitch: " << ((int)s->OriginalPitch); |
119 |
cout << ", Pitch Correction: " << ((int)s->PitchCorrection )<< endl; |
120 |
cout << "\t\tStart: " << s->Start << ", End: " << s->End; |
121 |
cout << ", Start Loop: " << s->StartLoop << ", End Loop: " << s->EndLoop << endl; |
122 |
cout << "\t\tSample Type: " << GetSampleType(s->SampleType) << ", Sample Link: " << s->SampleLink << ")" << endl; |
123 |
} |
124 |
} |
125 |
|
126 |
void PrintInstruments(sf2::File* sf) { |
127 |
cout << "Instruments (" << sf->GetInstrumentCount() << "): " << endl; |
128 |
for (int i = 0; i < sf->GetInstrumentCount(); i++) { |
129 |
sf2::Instrument* instr = sf->GetInstrument(i); |
130 |
cout << "\t" << instr->Name << " ("; |
131 |
cout << "Instrument bag: " << instr->InstBagNdx << ")" << endl; |
132 |
cout << "\t Regions (" << instr->GetRegionCount() << ")" << endl; |
133 |
|
134 |
if (instr->pGlobalRegion) PrintRegion(-1, instr->pGlobalRegion); |
135 |
|
136 |
for (int j = 0; j < instr->GetRegionCount(); j++) { |
137 |
PrintRegion(j, instr->GetRegion(j)); |
138 |
} |
139 |
cout << endl; |
140 |
} |
141 |
} |
142 |
|
143 |
void PrintPeresets(sf2::File* sf) { |
144 |
cout << "Presets (" << sf->GetPresetCount() << "): " << endl; |
145 |
for (int i = 0; i < sf->GetPresetCount(); i++) { /* exclude the terminal header - EOP */ |
146 |
sf2::Preset* p = sf->GetPreset(i); |
147 |
cout << "\t" << p->Name << " (Preset: " << p->PresetNum << ", Bank: " << p->Bank; |
148 |
cout << ", Preset bag: " << p->PresetBagNdx << ")" << endl; |
149 |
|
150 |
if (p->pGlobalRegion) PrintRegion(-1, p->pGlobalRegion); |
151 |
|
152 |
for (int j = 0; j < p->GetRegionCount(); j++) { |
153 |
PrintRegion(j, p->GetRegion(j)); |
154 |
} |
155 |
cout << endl; |
156 |
} |
157 |
} |
158 |
|
159 |
void PrintRegion(int idx, sf2::Region* reg) { |
160 |
if (idx == -1) cout << "\t\tGlobal Region " << endl; |
161 |
else cout << "\t\tRegion " << idx << endl; |
162 |
sf2::Sample* s = reg->GetSample(); |
163 |
if (s != NULL) cout << "\t\t Sample: " << s->Name << endl; |
164 |
cout << "\t\t Key range="; |
165 |
if (reg->loKey == NONE && reg->hiKey == NONE) cout << "None"; |
166 |
else cout << reg->loKey << "-" << reg->hiKey; |
167 |
cout << ", Velocity range="; |
168 |
if (reg->minVel == NONE && reg->maxVel == NONE) cout << "None" << endl; |
169 |
else cout << reg->minVel << "-" << reg->maxVel << endl; |
170 |
|
171 |
if (reg->pInstrument != NULL) { |
172 |
cout << "\t\t Instrument: " << reg->pInstrument->Name << endl; |
173 |
} |
174 |
|
175 |
cout << "\t\t\tEG1PreAttackDelay=" << reg->EG1PreAttackDelay << "s, EG1Attack=" << reg->EG1Attack; |
176 |
cout << "s, EG1Hold=" << reg->EG1Hold << "s, EG1Decay=" << reg->EG1Decay << "s, EG1Sustain="; |
177 |
cout << reg->EG1Sustain << "permille, EG1Release=" << reg->EG1Release << "s" << endl; |
178 |
|
179 |
cout << "\t\t\tEG2PreAttackDelay=" << reg->EG2PreAttackDelay << "s, EG2Attack=" << reg->EG2Attack; |
180 |
cout << "s, EG2Hold=" << reg->EG2Hold << "s, EG2Decay=" << reg->EG2Decay << "s, EG2Sustain="; |
181 |
cout << reg->EG2Sustain << "permille, EG2Release=" << reg->EG2Release << "s" << endl; |
182 |
|
183 |
cout << "\t\t\tModulators (" << reg->modulators.size() << ")" << endl; |
184 |
|
185 |
for (int i = 0; i < reg->modulators.size(); i++) { |
186 |
cout << "\t\t\tModulator " << i << endl; |
187 |
PrintModulatorItem(®->modulators[i]); |
188 |
} |
189 |
} |
190 |
|
191 |
void PrintModulatorItem(sf2::ModulatorItem* mod) { |
192 |
cout << "\t\t\t ModSrcOper" << endl; |
193 |
PrintModulator(mod->ModSrcOper); |
194 |
|
195 |
cout << "\t\t\t ModAmtSrcOper" << endl; |
196 |
PrintModulator(mod->ModAmtSrcOper); |
197 |
cout << "\t\t\t Amount: " << mod->ModAmount << endl; |
198 |
|
199 |
if (mod->ModDestOper & (1 << 15)) { |
200 |
cout << "\t\t\t ModDestOper: " << (mod->ModDestOper ^ (1 << 15)) << endl; |
201 |
} else { |
202 |
cout << "\t\t\t ModDestOper: " << mod->ModDestOper << endl; |
203 |
} |
204 |
} |
205 |
|
206 |
void PrintModulator(sf2::Modulator& mod) { |
207 |
cout << "\t\t\t\tController Type: " << GetControllerType(mod) << endl; |
208 |
cout << "\t\t\t\tController Source: " << GetControllerSource(mod) << endl; |
209 |
cout << "\t\t\t\tDirection: "; |
210 |
cout << (mod.Direction ? "max -> min" : "min -> max") << endl; |
211 |
cout << "\t\t\t\tPolarity: "; |
212 |
cout << (mod.Polarity ? "Bipolar" : "Unipolar") << endl; |
213 |
} |
214 |
|
215 |
string GetControllerType(sf2::Modulator& mod) { |
216 |
string s; |
217 |
switch(mod.Type) { |
218 |
case sf2::Modulator::LINEAR: |
219 |
s = "Linear"; break; |
220 |
case sf2::Modulator::CONCAVE: |
221 |
s = "Concave"; break; |
222 |
case sf2::Modulator::CONVEX: |
223 |
s = "Convex"; break; |
224 |
case sf2::Modulator::SWITCH: |
225 |
s = "Switch"; break; |
226 |
} |
227 |
|
228 |
return s; |
229 |
} |
230 |
|
231 |
string GetControllerSource(sf2::Modulator& mod) { |
232 |
if (mod.MidiPalete) { |
233 |
stringstream ss; |
234 |
ss << "MIDI controller " << mod.Index; |
235 |
return ss.str(); |
236 |
} |
237 |
|
238 |
string s; |
239 |
switch(mod.Index) { |
240 |
case sf2::Modulator::NO_CONTROLLER: |
241 |
s = "No controller"; break; |
242 |
case sf2::Modulator::NOTE_ON_VELOCITY: |
243 |
s = "Note-On Velocity"; break; |
244 |
case sf2::Modulator::NOTE_ON_KEY_NUMBER: |
245 |
s = "Note-On Key Number"; break; |
246 |
case sf2::Modulator::POLY_PRESSURE: |
247 |
s = "Poly Pressure"; break; |
248 |
case sf2::Modulator::CHANNEL_PRESSURE: |
249 |
s = "Channel Pressure"; break; |
250 |
case sf2::Modulator::PITCH_WHEEL: |
251 |
s = "Pitch Wheel"; break; |
252 |
case sf2::Modulator::PITCH_WHEEL_SENSITIVITY: |
253 |
s = "Pitch Wheel Sensitivity"; break; |
254 |
case sf2::Modulator::LINK: |
255 |
s = "Link"; break; |
256 |
default: s = "Unknown controller source"; |
257 |
} |
258 |
|
259 |
return s; |
260 |
} |
261 |
|
262 |
string Revision() { |
263 |
string s = "$Revision: 1.1 $"; |
264 |
return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword |
265 |
} |
266 |
|
267 |
void PrintVersion() { |
268 |
cout << "sf2dump revision " << Revision() << endl; |
269 |
cout << "using " << sf2::libraryName() << " " << sf2::libraryVersion() << endl; |
270 |
} |
271 |
|
272 |
void PrintUsage() { |
273 |
cout << "sf2dump - parses SF2 files and prints out the content." << endl; |
274 |
cout << endl; |
275 |
cout << "Usage: sf2dump [-v] FILE" << endl; |
276 |
cout << endl; |
277 |
cout << " -v Print version and exit." << endl; |
278 |
cout << endl; |
279 |
} |
280 |
|
281 |
string GetSampleType(uint16_t type) { |
282 |
switch(type) { |
283 |
case sf2::Sample::MONO_SAMPLE : return "Mono Sample"; |
284 |
case sf2::Sample::RIGHT_SAMPLE : return "Right Sample"; |
285 |
case sf2::Sample::LEFT_SAMPLE : return "Left Sample"; |
286 |
case sf2::Sample::LINKED_SAMPLE : return "Linked Sample"; |
287 |
case sf2::Sample::ROM_MONO_SAMPLE : return "ROM Mono Sample"; |
288 |
case sf2::Sample::ROM_RIGHT_SAMPLE : return "ROM Right Sample"; |
289 |
case sf2::Sample::ROM_LEFT_SAMPLE : return "ROM Left Sample"; |
290 |
case sf2::Sample::ROM_LINKED_SAMPLE : return "ROM Linked Sample"; |
291 |
default: return "Unknown"; |
292 |
} |
293 |
} |