1 #include "test.h"
2 #include "fluidsynth.h"
3 #include "fluid_sfont.h"
4 #include "fluid_defsfont.h"
5 #include "fluid_sys.h"
6
7 static void dump_sample(fluid_sample_t *sample);
8 static void dump_gens(const fluid_gen_t gen[]);
9 static void dump_mod(const fluid_mod_t *mod);
10 static void dump_preset_zone(fluid_preset_zone_t *zone);
11 static void dump_preset(fluid_preset_t *preset);
12 static void dump_inst_zone(fluid_inst_zone_t *zone);
13 static void dump_inst(fluid_inst_t *inst);
14 static void dump_defsfont(fluid_defsfont_t *defsfont);
15 static int inst_compare_func(const void *a, const void *b);
16 static fluid_list_t *collect_preset_insts(fluid_preset_t *preset, fluid_list_t *inst_list);
17
18 #define FMT_BUFSIZE (4096)
19 static int indent_level = 0;
20 static FILE *output = NULL;
21
22 static void fmt(const char *format, ...);
23 static void indent(void);
24 static void outdent(void);
25
26
main(int argc,char ** argv)27 int main(int argc, char **argv)
28 {
29 int ret = FLUID_FAILED;
30 int id;
31 fluid_sfont_t *sfont;
32 fluid_defsfont_t *defsfont;
33 fluid_settings_t *settings;
34 fluid_synth_t *synth;
35 const char *adrivers[1] = { NULL };
36
37 if (argc < 2)
38 {
39 fprintf(stderr, "Usage:\n");
40 fprintf(stderr, " dump_sfont <input_soundfont> [output_file]\n");
41 return FLUID_FAILED;
42 }
43
44 fluid_audio_driver_register(adrivers);
45
46 settings = new_fluid_settings();
47 if (settings == NULL)
48 {
49 return FLUID_FAILED;
50 }
51
52 synth = new_fluid_synth(settings);
53 if (synth == NULL)
54 {
55 goto EXIT;
56 }
57
58 id = fluid_synth_sfload(synth, argv[1], 1);
59 if (id < 0)
60 {
61 goto EXIT;
62 }
63
64 sfont = fluid_synth_get_sfont_by_id(synth, id);
65 if (sfont == NULL)
66 {
67 goto EXIT;
68 }
69
70 if (sfont->free != &fluid_defsfont_sfont_delete)
71 {
72 fprintf(stderr, "This tool only supports SoundFonts loaded by the default loader\n");
73 goto EXIT;
74 }
75
76 defsfont = (fluid_defsfont_t *)fluid_sfont_get_data(sfont);
77 if (defsfont == NULL)
78 {
79 goto EXIT;
80 }
81
82 if (argc < 3)
83 {
84 output = stdout;
85 }
86 else
87 {
88 output = fopen(argv[2], "w");
89 if (output == NULL)
90 {
91 fprintf(stderr, "Unable to open output file %s", argv[2]);
92 goto EXIT;
93 }
94 }
95
96 dump_defsfont(defsfont);
97
98 ret = FLUID_OK;
99
100 EXIT:
101 if (output && output != stdout)
102 {
103 fclose(output);
104 }
105 delete_fluid_synth(synth);
106 delete_fluid_settings(settings);
107
108 return ret;
109 }
110
dump_sample(fluid_sample_t * sample)111 static void dump_sample(fluid_sample_t *sample)
112 {
113 fmt("name: %s", sample->name);
114 fmt("source_start: %u", sample->source_start);
115 fmt("source_end: %u", sample->source_end);
116 fmt("source_loopstart: %u", sample->source_loopstart);
117 fmt("source_loopend: %u", sample->source_loopend);
118
119 fmt("start: %u", sample->start);
120 fmt("end: %u", sample->end);
121 fmt("loopstart: %u", sample->loopstart);
122 fmt("loopend: %u", sample->loopend);
123
124 fmt("samplerate: %u", sample->samplerate);
125 fmt("origpitch: %u", sample->origpitch);
126 fmt("pitchadj: %u", sample->pitchadj);
127 fmt("sampletype: %u", sample->sampletype);
128 }
129
dump_gens(const fluid_gen_t gen[])130 static void dump_gens(const fluid_gen_t gen[])
131 {
132 int i;
133
134 /* only dump generators if at least one is set */
135 for (i = 0; i < GEN_LAST; i++)
136 {
137 if (gen[i].flags)
138 {
139 break;
140 }
141 }
142
143 if (i == GEN_LAST)
144 {
145 return;
146 }
147
148 fmt("generators:");
149 indent();
150 for (i = 0; i < GEN_LAST; i++)
151 {
152 if (gen[i].flags)
153 {
154 fmt("%s: %.2f", fluid_gen_name(i), gen[i].val);
155 }
156 }
157 outdent();
158 }
159
dump_mod(const fluid_mod_t * mod)160 static void dump_mod(const fluid_mod_t *mod)
161 {
162 fmt("dest: %s", fluid_gen_name(mod->dest));
163 fmt("src1: %u", mod->src1);
164 fmt("flags1: %u", mod->flags1);
165 fmt("src2: %u", mod->src2);
166 fmt("flags2: %u", mod->flags2);
167 fmt("amount: %.2f", mod->amount);
168 }
169
dump_preset_zone(fluid_preset_zone_t * zone)170 static void dump_preset_zone(fluid_preset_zone_t *zone)
171 {
172 int i;
173 fluid_mod_t *mod;
174
175 fmt("name: %s", zone->name);
176 if (zone->inst)
177 {
178 fmt("instrument: %s (index %d)", zone->inst->name, zone->inst->source_idx);
179 }
180 fmt("key_range: %d - %d", zone->range.keylo, zone->range.keyhi);
181 fmt("vel_range: %d - %d", zone->range.vello, zone->range.velhi);
182 dump_gens(zone->gen);
183
184 if (zone->mod)
185 {
186 fmt("modulators:");
187 for (i = 0, mod = zone->mod; mod; mod = mod->next, i++)
188 {
189 fmt("- modulator: %d", i);
190 indent();
191 dump_mod(mod);
192 outdent();
193 }
194 }
195 }
196
dump_preset(fluid_preset_t * preset)197 static void dump_preset(fluid_preset_t *preset)
198 {
199 int i;
200 fluid_preset_zone_t *zone;
201
202 fluid_defpreset_t *defpreset = fluid_preset_get_data(preset);
203 if (defpreset == NULL)
204 {
205 return;
206 }
207
208 fmt("name: %s", defpreset->name);
209 fmt("bank: %u", defpreset->bank);
210 fmt("num: %u", defpreset->num);
211
212 if (defpreset->global_zone)
213 {
214 fmt("global_zone:");
215 indent();
216 dump_preset_zone(defpreset->global_zone);
217 outdent();
218 }
219
220 fmt("zones:");
221 for (i = 0, zone = defpreset->zone; zone; zone = fluid_preset_zone_next(zone), i++)
222 {
223 fmt("- zone: %d", i);
224 if (zone == NULL)
225 {
226 continue;
227 }
228
229 indent();
230 dump_preset_zone(zone);
231 outdent();
232 }
233 }
234
dump_inst_zone(fluid_inst_zone_t * zone)235 static void dump_inst_zone(fluid_inst_zone_t *zone)
236 {
237 int i;
238 fluid_mod_t *mod;
239
240 fmt("name: %s", zone->name);
241 if (zone->sample)
242 {
243 fmt("sample: %s", zone->sample->name);
244 }
245 fmt("key_range: %d - %d", zone->range.keylo, zone->range.keyhi);
246 fmt("vel_range: %d - %d", zone->range.vello, zone->range.velhi);
247 dump_gens(zone->gen);
248 if (zone->mod)
249 {
250 fmt("modulators:");
251 for (i = 0, mod = zone->mod; mod; mod = mod->next, i++)
252 {
253 fmt("- modulator: %d", i);
254 indent();
255 dump_mod(mod);
256 outdent();
257 }
258 }
259 }
260
dump_inst(fluid_inst_t * inst)261 static void dump_inst(fluid_inst_t *inst)
262 {
263 int i;
264 fluid_inst_zone_t *zone;
265
266 fmt("name: %s", inst->name);
267
268 if (inst->global_zone)
269 {
270 fmt("global_zone:");
271 indent();
272 dump_inst_zone(inst->global_zone);
273 outdent();
274 }
275
276 fmt("zones:");
277 for (i = 0, zone = inst->zone; zone; zone = fluid_inst_zone_next(zone), i++)
278 {
279 fmt("- zone: %d", i);
280 if (zone == NULL)
281 {
282 continue;
283 }
284
285 indent();
286 dump_inst_zone(zone);
287 outdent();
288 }
289 }
290
inst_compare_func(const void * a,const void * b)291 static int inst_compare_func(const void *a, const void *b)
292 {
293 const fluid_inst_t *inst_a = a;
294 const fluid_inst_t *inst_b = b;
295
296 return inst_a->source_idx - inst_b->source_idx;
297 }
298
collect_preset_insts(fluid_preset_t * preset,fluid_list_t * inst_list)299 static fluid_list_t *collect_preset_insts(fluid_preset_t *preset, fluid_list_t *inst_list)
300 {
301 fluid_preset_zone_t *zone;
302 fluid_defpreset_t *defpreset = fluid_preset_get_data(preset);
303 if (defpreset == NULL)
304 {
305 return inst_list;
306 }
307
308 if (defpreset->global_zone && defpreset->global_zone->inst &&
309 fluid_list_idx(inst_list, defpreset->global_zone->inst) == -1)
310 {
311 inst_list = fluid_list_prepend(inst_list, defpreset->global_zone->inst);
312 }
313
314 for (zone = defpreset->zone; zone; zone = fluid_preset_zone_next(zone))
315 {
316 if (zone->inst && (fluid_list_idx(inst_list, zone->inst) == -1))
317 {
318 inst_list = fluid_list_prepend(inst_list, zone->inst);
319 }
320 }
321
322 return inst_list;
323 }
324
325
dump_defsfont(fluid_defsfont_t * defsfont)326 static void dump_defsfont(fluid_defsfont_t *defsfont)
327 {
328 int i;
329 fluid_list_t *list;
330 fluid_sample_t *sample;
331 fluid_preset_t *preset;
332 fluid_inst_t *inst;
333 fluid_list_t *inst_list = NULL;
334
335 fmt("samplepos: %u", defsfont->samplepos);
336 fmt("samplesize: %u", defsfont->samplesize);
337 fmt("sample24pos: %u", defsfont->sample24pos);
338 fmt("sample24size: %u", defsfont->sample24size);
339
340 fmt("presets:");
341 for (i = 0, list = defsfont->preset; list; list = fluid_list_next(list), i++)
342 {
343 preset = (fluid_preset_t *)fluid_list_get(list);
344 fmt("- preset: %d", i);
345 if (preset == NULL)
346 {
347 continue;
348 }
349
350 indent();
351 dump_preset(preset);
352 outdent();
353 fmt("");
354
355 inst_list = collect_preset_insts(preset, inst_list);
356 }
357
358 inst_list = fluid_list_sort(inst_list, inst_compare_func);
359
360 fmt("instruments:");
361 for (list = inst_list; list; list = fluid_list_next(list))
362 {
363 inst = (fluid_inst_t *)fluid_list_get(list);
364 fmt("- instrument: %d", inst->source_idx);
365 indent();
366 dump_inst(inst);
367 outdent();
368 fmt("");
369 }
370
371 delete_fluid_list(inst_list);
372
373 fmt("samples:");
374 for (i = 0, list = defsfont->sample; list; list = fluid_list_next(list), i++)
375 {
376 sample = (fluid_sample_t *)fluid_list_get(list);
377 fmt("- sample: %d", i);
378 if (sample == NULL)
379 {
380 continue;
381 }
382
383 indent();
384 dump_sample(sample);
385 outdent();
386 fmt("");
387 }
388 }
389
390
fmt(const char * format,...)391 static void fmt(const char *format, ...)
392 {
393 char buf[FMT_BUFSIZE];
394 va_list args;
395 int len;
396 int i;
397
398 va_start(args, format);
399 len = FLUID_VSNPRINTF(buf, FMT_BUFSIZE, format, args);
400 va_end(args);
401
402 if (len < 0)
403 {
404 FLUID_LOG(FLUID_ERR, "max buffer size exceeded");
405 return;
406 }
407
408 buf[FMT_BUFSIZE - 1] = '\0';
409
410 for (i = 0; i < indent_level; i++)
411 {
412 fprintf(output, " ");
413 }
414
415 fwrite(buf, 1, FLUID_STRLEN(buf), output);
416 fprintf(output, "\n");
417 }
418
indent(void)419 static void indent(void)
420 {
421 indent_level += 1;
422 }
423
outdent(void)424 static void outdent(void)
425 {
426 if (indent_level > 0)
427 {
428 indent_level -= 1;
429 }
430 }
431