1 // Licensed GNU LGPL v3 or later: http://www.gnu.org/licenses/lgpl.html
2
3 #include <assert.h>
4 #include <stdio.h>
5 #include <fcntl.h>
6 #include <string.h>
7 #include <errno.h>
8
9 #include <vector>
10 #include <map>
11 #include <set>
12 #include <algorithm>
13
14 #include "config.h"
15 #include "smgenericin.hh"
16 #include "smmain.hh"
17 #include "smjobqueue.hh"
18 #include "smwavset.hh"
19 #include "smutils.hh"
20 #include "smwavdata.hh"
21 #include "sminstrument.hh"
22 #include <stdlib.h>
23
24 #if 1
25 static inline void
debug(const char * fmt,...)26 debug (const char *fmt, ...)
27 {
28 }
29 #else
30 #define debug printf
31 #endif
32
33 /* avoid problems with SpectMorph::Instrument and SpectMorph::Sample */
34 using SpectMorph::GenericIn;
35 using SpectMorph::JobQueue;
36 using SpectMorph::WavSet;
37 using SpectMorph::WavSetWave;
38 using SpectMorph::WavData;
39 using SpectMorph::Main;
40
41 using SpectMorph::string_printf;
42
43 using std::string;
44 using std::vector;
45 using std::map;
46 using std::sort;
47 using std::set;
48
49 static string
get_current_dir()50 get_current_dir()
51 {
52 char *dir = g_get_current_dir();
53 string dir_str = dir;
54 g_free (dir);
55
56 return dir_str;
57 }
58
59 enum {
60 GEN_PAN = 17,
61 GEN_INSTRUMENT = 41,
62 GEN_KEY_RANGE = 43,
63 GEN_VELOCITY_RANGE = 44,
64 GEN_SAMPLE = 53,
65 GEN_SAMPLE_MODES = 54,
66 GEN_ROOT_KEY = 58
67 };
68
69 struct Generator
70 {
71 int generator;
72
73 // amount generators:
74 int amount;
75
76 // range generators:
77 int range_min;
78 int range_max;
79
80 void read (GenericIn *in);
81 };
82
83 struct Zone
84 {
85 vector<Generator> generators;
86 };
87
88 struct Preset
89 {
90 string name;
91 int preset;
92 int bank;
93 int preset_bag_index;
94
95 vector<Zone> zones;
96 };
97
98 struct BagEntry
99 {
100 int gen_index;
101 int mod_index;
102 };
103
104 struct Instrument
105 {
106 string name;
107 int instrument_bag_index;
108 vector<Zone> zones;
109 };
110
111 struct Sample
112 {
113 string name;
114 int start, end;
115 int startloop, endloop;
116 int srate;
117 int origpitch;
118 int pitchcorrect;
119 int samplelink;
120 int sampletype;
121 };
122
123 vector<Preset> presets;
124 vector<BagEntry> preset_bag;
125 vector<Generator> preset_gen;
126 vector<Instrument> instruments;
127 vector<BagEntry> instrument_bag;
128 vector<Generator> instrument_gen;
129 vector<Sample> samples;
130
131 string
read_fourcc(GenericIn * in)132 read_fourcc (GenericIn *in)
133 {
134 string fcc;
135
136 for (int i = 0; i < 4; i++)
137 {
138 char c = in->get_byte();
139 fcc += c;
140 }
141
142 return fcc;
143 }
144
145 int
read_ui32(GenericIn * in)146 read_ui32 (GenericIn *in)
147 {
148 int c0 = in->get_byte();
149 int c1 = in->get_byte();
150 int c2 = in->get_byte();
151 int c3 = in->get_byte();
152
153 return c0 + (c1 << 8) + (c2 << 16) + (c3 << 24);
154 }
155
156 int
read_ui16(GenericIn * in)157 read_ui16 (GenericIn *in)
158 {
159 int c0 = in->get_byte();
160 int c1 = in->get_byte();
161
162 return c0 + (c1 << 8);
163 }
164
165 int
read_si16(GenericIn * in)166 read_si16 (GenericIn *in)
167 {
168 int c0 = in->get_byte();
169 int c1 = int (char (in->get_byte()));
170
171 return c0 + (c1 << 8);
172 }
173
174 string
read_string(GenericIn * in,int len)175 read_string (GenericIn *in, int len)
176 {
177 string result;
178
179 while (len)
180 {
181 int b = in->get_byte();
182 if (b == 0)
183 assert (len == 1 || len == 2);
184 else
185 result += char (b);
186 len--;
187 }
188 return result;
189 }
190
191 string
read_fixed_string(GenericIn * in,int len)192 read_fixed_string (GenericIn *in, int len)
193 {
194 string result;
195 bool eos = false;
196 while (len)
197 {
198 int b = in->get_byte();
199
200 if (b == 0)
201 eos = true;
202
203 if (!eos)
204 result += char (b);
205 len--;
206 }
207 return result;
208 }
209
210 void
read(GenericIn * in)211 Generator::read (GenericIn *in)
212 {
213 generator = read_ui16 (in);
214 range_min = range_max = amount = 0;
215 if (generator == GEN_KEY_RANGE || generator == GEN_VELOCITY_RANGE)
216 {
217 range_min = in->get_byte();
218 range_max = in->get_byte();
219 }
220 else if (generator == GEN_PAN)
221 {
222 amount = read_si16 (in);
223 }
224 else
225 {
226 amount = read_ui16 (in);
227 }
228 }
229
230 void
read_ifil(GenericIn * in,int len)231 read_ifil (GenericIn *in, int len)
232 {
233 assert (len == 4);
234 int major = read_ui16 (in);
235 int minor = read_ui16 (in);
236 debug ("format version %d.%d\n", major, minor);
237 }
238
239 void
read_INAM(GenericIn * in,int len)240 read_INAM (GenericIn *in, int len)
241 {
242 string result = read_string (in, len);
243 debug ("name '%s'\n", result.c_str());
244 }
245
246 void
read_isng(GenericIn * in,int len)247 read_isng (GenericIn *in, int len)
248 {
249 string result = read_string (in, len);
250 debug ("target '%s'\n", result.c_str());
251 }
252
253 void
read_IPRD(GenericIn * in,int len)254 read_IPRD (GenericIn *in, int len)
255 {
256 string result = read_string (in, len);
257 debug ("product '%s'\n", result.c_str());
258 }
259
260 void
read_IENG(GenericIn * in,int len)261 read_IENG (GenericIn *in, int len)
262 {
263 string result = read_string (in, len);
264 debug ("engineer '%s'\n", result.c_str());
265 }
266
267 void
read_ISFT(GenericIn * in,int len)268 read_ISFT (GenericIn *in, int len)
269 {
270 string result = read_string (in, len);
271 debug ("tool '%s'\n", result.c_str());
272 }
273
274 void
read_ICRD(GenericIn * in,int len)275 read_ICRD (GenericIn *in, int len)
276 {
277 string result = read_string (in, len);
278 debug ("creation date '%s'\n", result.c_str());
279 }
280
281 void
read_ICMT(GenericIn * in,int len)282 read_ICMT (GenericIn *in, int len)
283 {
284 string result = read_string (in, len);
285 debug ("comment '%s'\n", result.c_str());
286 }
287
288 void
read_ICOP(GenericIn * in,int len)289 read_ICOP (GenericIn *in, int len)
290 {
291 string result = read_string (in, len);
292 debug ("copyright '%s'\n", result.c_str());
293 }
294
295 void
read_phdr(GenericIn * in,int len)296 read_phdr (GenericIn *in, int len)
297 {
298 debug ("phdr len = %d\n", len);
299
300 while (len >= 38)
301 {
302 Preset p;
303 p.name = read_fixed_string (in, 20);
304 p.preset = read_ui16 (in);
305 p.bank = read_ui16 (in);
306 p.preset_bag_index = read_ui16 (in);
307 presets.push_back (p);
308
309 debug ("preset '%s'\n", p.name.c_str());
310 debug ("preset %d\n", p.preset);
311 debug ("bank %d\n", p.bank);
312 debug ("preset bag ndx %d\n", p.preset_bag_index);
313 debug ("library %d\n", read_ui32 (in));
314 debug ("genre %d\n", read_ui32 (in));
315 debug ("morphology %d\n", read_ui32 (in));
316 len -= 38;
317 }
318 }
319
320 void
read_pbag(GenericIn * in,int len)321 read_pbag (GenericIn *in, int len)
322 {
323 debug ("pbag len = %d\n", len);
324 while (len >= 4)
325 {
326 BagEntry b;
327 b.gen_index = read_ui16 (in);
328 b.mod_index = read_ui16 (in);
329 preset_bag.push_back (b);
330
331 debug ("genndx %d\n", b.gen_index);
332 debug ("modndx %d\n", b.mod_index);
333 len -= 4;
334 }
335 }
336
337 void
read_pmod(GenericIn * in,int len)338 read_pmod (GenericIn *in, int len)
339 {
340 debug ("pmod len = %d\n", len);
341 while (len >= 10)
342 {
343 debug ("modsrcoper %d\n", read_ui16 (in));
344 debug ("moddestoper %d\n", read_ui16 (in));
345 debug ("modamount %d\n", read_ui16 (in));
346 debug ("modamtsrcoper %d\n", read_ui16 (in));
347 debug ("modtransoper %d\n", read_ui16 (in));
348 len -= 10;
349 }
350 }
351
352 void
read_pgen(GenericIn * in,int len)353 read_pgen (GenericIn *in, int len)
354 {
355 debug ("pgen len = %d\n", len);
356 while (len >= 4)
357 {
358 Generator g;
359 g.read (in);
360 preset_gen.push_back (g);
361
362 debug ("generator %d\n", g.generator);
363 debug ("amount %d\n", g.amount);
364 len -= 4;
365 }
366 }
367
368 void
read_inst(GenericIn * in,int len)369 read_inst (GenericIn *in, int len)
370 {
371 debug ("inst len = %d\n", len);
372 while (len >= 22)
373 {
374 Instrument i;
375 i.name = read_fixed_string (in, 20);
376 i.instrument_bag_index = read_ui16 (in);
377 instruments.push_back (i);
378
379 debug ("instname %s\n", i.name.c_str());
380 debug ("bagindex %d\n", i.instrument_bag_index);
381 len -= 22;
382 }
383 }
384
385 void
read_ibag(GenericIn * in,int len)386 read_ibag (GenericIn *in, int len)
387 {
388 debug ("ibag len = %d\n", len);
389 while (len >= 4)
390 {
391 BagEntry b;
392 b.gen_index = read_ui16 (in);
393 b.mod_index = read_ui16 (in);
394 instrument_bag.push_back (b);
395
396 debug ("instgenidx %d\n", b.gen_index);
397 debug ("instmodidx %d\n", b.mod_index);
398 len -= 4;
399 }
400 }
401
402 void
read_imod(GenericIn * in,int len)403 read_imod (GenericIn *in, int len)
404 {
405 debug ("imod len = %d\n", len);
406 while (len >= 10)
407 {
408 debug ("modsrcoper %d\n", read_ui16 (in));
409 debug ("moddestoper %d\n", read_ui16 (in));
410 debug ("modamount %d\n", read_ui16 (in));
411 debug ("modamtsrcoper %d\n", read_ui16 (in));
412 debug ("modtransoper %d\n", read_ui16 (in));
413 len -= 10;
414 }
415 }
416
417 void
read_igen(GenericIn * in,int len)418 read_igen (GenericIn *in, int len)
419 {
420 debug ("igen len = %d\n", len);
421 while (len >= 4)
422 {
423 Generator g;
424 g.read (in);
425 instrument_gen.push_back (g);
426
427 debug ("generator %d\n", g.generator);
428 debug ("amount %d\n", g.amount);
429 len -= 4;
430 }
431 }
432
433 void
read_shdr(GenericIn * in,int len)434 read_shdr (GenericIn *in, int len)
435 {
436 debug ("shdr len = %d\n", len);
437 while (len >= 46)
438 {
439 Sample s;
440 s.name = read_fixed_string (in, 20);
441 s.start = read_ui32 (in);
442 s.end = read_ui32 (in);
443 s.startloop = read_ui32 (in);
444 s.endloop = read_ui32 (in);
445 s.srate = read_ui32 (in);
446 s.origpitch = in->get_byte();
447 s.pitchcorrect = in->get_byte();
448 s.samplelink = read_ui16 (in);
449 s.sampletype = read_ui16 (in);
450 samples.push_back (s);
451
452 debug ("samplename %s\n", s.name.c_str());
453 debug ("start %d\n", s.start);
454 debug ("end %d\n", s.end);
455 debug ("startloop %d\n", s.startloop);
456 debug ("endloop %d\n", s.endloop);
457 debug ("srate %d\n", s.srate);
458 debug ("origpitch %d\n", s.origpitch);
459 debug ("pitchcorrect %d\n", s.pitchcorrect);
460 debug ("samplelink %d\n", s.samplelink);
461 debug ("sampletype %d\n", s.sampletype);
462 len -= 46;
463 }
464 }
465
466 const char *
gen2name(int i)467 gen2name (int i)
468 {
469 struct G2N
470 {
471 int gen;
472 const char *name;
473 } g2n[] = {
474 { 8, "initial-filter-fc" },
475 { GEN_PAN, "pan" },
476 { 35, "vol-env-hold" },
477 { 36, "vol-env-decay" },
478 { 37, "vol-env-sustain" },
479 { 38, "vol-env-release" },
480 { GEN_INSTRUMENT, "instrument" },
481 { GEN_KEY_RANGE, "key-range" },
482 { GEN_VELOCITY_RANGE, "velocity-range" },
483 { GEN_SAMPLE, "sample-id" },
484 { GEN_SAMPLE_MODES, "sample-modes" },
485 { GEN_ROOT_KEY, "root-key" },
486 { 0, NULL }
487 };
488 for (int k = 0; g2n[k].name; k++)
489 if (g2n[k].gen == i)
490 return g2n[k].name;
491 return "unknown";
492 }
493
494 const Generator *
find_gen(int id,const vector<Generator> & generators)495 find_gen (int id, const vector<Generator>& generators)
496 {
497 for (vector<Generator>::const_iterator gi = generators.begin(); gi != generators.end(); gi++)
498 if (gi->generator == id)
499 return &(*gi);
500
501 return NULL; // not found
502 }
503
504 void
xsystem(const string & cmd)505 xsystem (const string& cmd)
506 {
507 printf ("# %s\n", cmd.c_str());
508 int rc = system (cmd.c_str());
509 if (rc != 0)
510 {
511 printf ("command execution failed: %d\n", WEXITSTATUS (rc));
512 exit (1);
513 }
514 }
515
516 vector<float> sample_data;
517
518 struct Options
519 {
520 string program_name;
521 enum { NONE, LIST, DUMP, IMPORT } command;
522 int midi_note;
523 bool fast_import;
524 bool debug;
525 bool mono_flat;
526 bool sminst = false;
527 int max_jobs;
528 string config_filename;
529 string smenc;
530 string output_filename;
531
532 Options();
533 void parse (int *argc_p, char **argv_p[]);
534 static void print_usage();
535 } options;
536
537 #include "stwutils.hh"
538
Options()539 Options::Options()
540 {
541 command = NONE;
542 program_name = "smsfimport";
543 midi_note = -1; // all
544 fast_import = false;
545 debug = false;
546 max_jobs = 1;
547 smenc = "smenc";
548 mono_flat = false;
549 }
550
551 void
parse(int * argc_p,char ** argv_p[])552 Options::parse (int *argc_p,
553 char **argv_p[])
554 {
555 guint argc = *argc_p;
556 gchar **argv = *argv_p;
557 unsigned int i, e;
558
559 for (i = 1; i < argc; i++)
560 {
561 const char *opt_arg;
562 if (strcmp (argv[i], "--help") == 0 ||
563 strcmp (argv[i], "-h") == 0)
564 {
565 print_usage();
566 exit (0);
567 }
568 else if (strcmp (argv[i], "--version") == 0 || strcmp (argv[i], "-v") == 0)
569 {
570 printf ("%s %s\n", program_name.c_str(), VERSION);
571 exit (0);
572 }
573 else if (check_arg (argc, argv, &i, "-m", &opt_arg))
574 {
575 midi_note = atoi (opt_arg);
576 }
577 else if (check_arg (argc, argv, &i, "-j", &opt_arg))
578 {
579 max_jobs = atoi (opt_arg);
580 }
581 else if (check_arg (argc, argv, &i, "--fast"))
582 {
583 fast_import = true;
584 }
585 else if (check_arg (argc, argv, &i, "--debug"))
586 {
587 debug = true;
588 }
589 else if (check_arg (argc, argv, &i, "--config", &opt_arg))
590 {
591 config_filename = opt_arg;
592 }
593 else if (check_arg (argc, argv, &i, "--cache"))
594 {
595 smenc = "smenccache";
596 }
597 else if (check_arg (argc, argv, &i, "--output", &opt_arg))
598 {
599 output_filename = opt_arg;
600 }
601 else if (check_arg (argc, argv, &i, "--mono-flat"))
602 {
603 mono_flat = true;
604 }
605 else if (check_arg (argc, argv, &i, "--sminst"))
606 {
607 sminst = true;
608 }
609 }
610
611 bool resort_required = true;
612
613 while (resort_required)
614 {
615 /* resort argc/argv */
616 e = 1;
617 for (i = 1; i < argc; i++)
618 if (argv[i])
619 {
620 argv[e++] = argv[i];
621 if (i >= e)
622 argv[i] = NULL;
623 }
624 *argc_p = e;
625 resort_required = false;
626
627 // parse command
628 if (*argc_p >= 2 && command == NONE)
629 {
630 string str = argv[1];
631 if (str == "list")
632 {
633 command = LIST;
634 }
635 else if (str == "dump")
636 {
637 command = DUMP;
638 }
639 else if (str == "import")
640 {
641 command = IMPORT;
642 }
643
644 if (command != NONE)
645 {
646 argv[1] = NULL;
647 resort_required = true;
648 }
649 }
650 }
651 }
652
653
654 void
print_usage()655 Options::print_usage ()
656 {
657 printf ("usage: %s <command> [ <options> ] [ <command specific args...> ]\n", options.program_name.c_str());
658 printf ("\n");
659 printf ("command specific args:\n");
660 printf ("\n");
661 printf (" %s list [ <options> ] <sf2_filename>\n", options.program_name.c_str());
662 printf (" %s dump [ <options> ] <sf2_filename> [ <preset_name> ]\n", options.program_name.c_str());
663 printf (" %s import [ <options> ] <sf2_filename> <preset_name>\n", options.program_name.c_str());
664 printf ("\n");
665 printf ("options:\n");
666 printf (" -h, --help help for %s\n", options.program_name.c_str());
667 printf (" -v, --version print version\n");
668 printf ("\n");
669 }
670
671 int
read_sf2(const string & filename)672 read_sf2 (const string& filename)
673 {
674 GenericIn *in = GenericIn::open (filename.c_str());
675 if (!in)
676 {
677 fprintf (stderr, "%s: error opening file %s\n", options.program_name.c_str(), filename.c_str());
678 return 1;
679 }
680
681 string fcc = read_fourcc (in);
682 if (fcc != "RIFF")
683 {
684 fprintf (stderr, "not a RIFF file\n");
685 return 1;
686 }
687
688 int len = read_ui32 (in);
689 debug ("len = %d\n", len);
690
691 fcc = read_fourcc (in);
692 if (fcc != "sfbk")
693 {
694 fprintf (stderr, "missing sfbk chunk\n");
695 return 1;
696 }
697 fcc = read_fourcc (in);
698 debug ("fcc<list> = %s\n", fcc.c_str());
699 len = read_ui32 (in);
700 debug ("len = %d\n", len);
701
702 size_t list_end_pos = len + in->get_pos();
703
704 fcc = read_fourcc (in);
705 debug ("fcc<info> = %s\n", fcc.c_str());
706
707 while (in->get_pos() < list_end_pos)
708 {
709 fcc = read_fourcc (in);
710 len = read_ui32 (in);
711
712 if (fcc == "ifil")
713 read_ifil (in, len);
714 else if (fcc == "INAM")
715 read_INAM (in, len);
716 else if (fcc == "isng")
717 read_isng (in, len);
718 else if (fcc == "IPRD")
719 read_IPRD (in, len);
720 else if (fcc == "IENG")
721 read_IENG (in, len);
722 else if (fcc == "ISFT")
723 read_ISFT (in, len);
724 else if (fcc == "ICRD")
725 read_ICRD (in, len);
726 else if (fcc == "ICMT")
727 read_ICMT (in, len);
728 else if (fcc == "ICOP")
729 read_ICOP (in, len);
730 else
731 {
732 printf ("unhandled chunk: %s\n", fcc.c_str());
733 return 1;
734 }
735 }
736
737 debug ("position = %zd\n", in->get_pos());
738 fcc = read_fourcc (in);
739 debug ("fcc<list> = %s\n", fcc.c_str());
740 len = read_ui32 (in);
741 debug ("len = %d\n", len);
742
743 fcc = read_fourcc (in);
744 debug ("fcc<info> = %s\n", fcc.c_str());
745 fcc = read_fourcc (in);
746 debug ("fcc<info> = %s\n", fcc.c_str());
747 len = read_ui32 (in);
748 debug ("len = %d\n", len);
749
750 while (len)
751 {
752 sample_data.push_back (read_si16 (in) * (1 / 32768.0));
753 len -= 2;
754 }
755 debug ("sample_data len: %zd\n", sample_data.size());
756
757 fcc = read_fourcc (in);
758 debug ("fcc<list> = %s\n", fcc.c_str());
759 len = read_ui32 (in);
760 debug ("len = %d\n", len);
761
762 list_end_pos = len + in->get_pos();
763
764 fcc = read_fourcc (in);
765 debug ("fcc<pdta> = %s\n", fcc.c_str());
766
767 while (in->get_pos() < list_end_pos)
768 {
769 fcc = read_fourcc (in);
770 len = read_ui32 (in);
771
772 if (fcc == "phdr")
773 read_phdr (in, len);
774 else if (fcc == "pbag")
775 read_pbag (in, len);
776 else if (fcc == "pmod")
777 read_pmod (in, len);
778 else if (fcc == "pgen")
779 read_pgen (in, len);
780 else if (fcc == "inst")
781 read_inst (in, len);
782 else if (fcc == "ibag")
783 read_ibag (in, len);
784 else if (fcc == "imod")
785 read_imod (in, len);
786 else if (fcc == "igen")
787 read_igen (in, len);
788 else if (fcc == "shdr")
789 read_shdr (in, len);
790 else
791 {
792 printf ("unhandled chunk: %s\n", fcc.c_str());
793 in->skip (len);
794 }
795 }
796 assert (in->get_byte() == -1);
797
798 for (vector<Preset>::iterator pi = presets.begin(); pi != presets.end(); pi++)
799 {
800 debug ("Preset %s\n", pi->name.c_str());
801 debug (" bank %d\n", pi->bank);
802 debug (" preset %d\n", pi->preset);
803
804 if ((pi + 1) < presets.end())
805 {
806
807 int start = pi->preset_bag_index, end = (pi + 1)->preset_bag_index;
808 for (vector<BagEntry>::iterator bi = preset_bag.begin() + start; bi != preset_bag.begin() + end; bi++)
809 {
810 Zone zone; // FIXME! needs to be in inner loop
811
812 debug (" genndx %d\n", bi->gen_index);
813 debug (" modndx %d\n", bi->mod_index);
814 if ((bi + 1) < preset_bag.end())
815 for (int gndx = bi->gen_index; gndx < (bi + 1)->gen_index; gndx++)
816 {
817 debug (" generator %d (%s)\n", preset_gen[gndx].generator, gen2name (preset_gen[gndx].generator));
818 debug (" amount %d\n", preset_gen[gndx].amount);
819 if (preset_gen[gndx].generator == 41) // instrument id
820 {
821 size_t id = preset_gen[gndx].amount;
822 assert (id >= 0 && id < instruments.size());
823 debug (" -> %s\n", instruments[id].name.c_str());
824 }
825 zone.generators.push_back (preset_gen[gndx]);
826 }
827 pi->zones.push_back (zone);
828 }
829 }
830 }
831 for (vector<Instrument>::iterator ii = instruments.begin(); ii != instruments.end(); ii++)
832 {
833 debug ("Instrument %s\n", ii->name.c_str());
834 if ((ii + 1) < instruments.end())
835 {
836
837 int start = ii->instrument_bag_index, end = (ii + 1)->instrument_bag_index;
838 for (vector<BagEntry>::iterator bi = instrument_bag.begin() + start; bi != instrument_bag.begin() + end; bi++)
839 {
840 Zone zone;
841
842 debug (" genndx %d\n", bi->gen_index);
843 debug (" modndx %d\n", bi->mod_index);
844 if ((bi + 1) < instrument_bag.end())
845 for (int gndx = bi->gen_index; gndx < (bi + 1)->gen_index; gndx++)
846 {
847 debug (" generator %d (%s)\n", instrument_gen[gndx].generator, gen2name (instrument_gen[gndx].generator));
848 debug (" amount %d\n", instrument_gen[gndx].amount);
849 if (instrument_gen[gndx].generator == 53) // sample id
850 {
851 size_t id = instrument_gen[gndx].amount;
852 assert (id >= 0 && id < samples.size());
853 debug (" -> %s\n", samples[id].name.c_str());
854 }
855 zone.generators.push_back (instrument_gen[gndx]);
856 }
857 ii->zones.push_back (zone);
858 }
859 }
860 }
861 #if 0
862 for (vector<Sample>::iterator si = samples.begin(); si != samples.end(); si++)
863 {
864 printf ("Sample %s\n", si->name.c_str());
865 }
866 #endif
867 delete in;
868 return 0;
869 }
870
871 string
check_import(const Preset & p)872 check_import (const Preset& p)
873 {
874 if (p.zones.size() == 1)
875 {
876 //printf ("PRESET: %s\n", p.name.c_str());
877 const Zone& zone = p.zones[0];
878 int inst_index = -1;
879 for (vector<Generator>::const_iterator gi = zone.generators.begin(); gi != zone.generators.end(); gi++)
880 {
881 if (gi->generator == GEN_INSTRUMENT)
882 {
883 assert (inst_index == -1);
884 inst_index = gi->amount;
885 }
886 }
887 assert (inst_index >= 0);
888 //printf ("inst_index=%d\n", inst_index);
889
890 vector<int> key_count (128);
891
892 const Instrument& instrument = instruments[inst_index];
893 for (vector<Zone>::const_iterator zi = instrument.zones.begin(); zi != instrument.zones.end(); zi++)
894 {
895 // const size_t zone_index = zi - instrument.zones.begin();
896 // printf ("zone %zd:\n", zone_index);
897 // int root_key = -1;
898
899 const Generator *gi; // = find_gen (GEN_ROOT_KEY, zi->generators);
900 //if (gi)
901 //root_key = gi->amount;
902
903 gi = find_gen (GEN_SAMPLE, zi->generators);
904 if (gi)
905 {
906 size_t id = gi->amount;
907 assert (id >= 0 && id < samples.size());
908 //printf (" * sample = %s\n", samples[id].name.c_str());
909
910 /* default: map to all keys */
911 int kr_min = 0;
912 int kr_max = 127;
913
914 gi = find_gen (GEN_KEY_RANGE, zi->generators);
915 if (gi)
916 {
917 kr_min = gi->range_min;
918 kr_max = gi->range_max;
919 }
920 //printf (" * key range = %d..%d\n", kr_min, kr_max);
921 for (int i = kr_min; i < kr_max; i++)
922 key_count[i] += 1;
923 }
924 }
925 for (size_t i = 0; i < key_count.size(); i++)
926 if (key_count[i] > 1)
927 return "noimport (key range overlap)";
928
929 return "importable";
930 }
931 else
932 return "noimport (> 1 zone)";
933 }
934
935 void
list_sf2()936 list_sf2()
937 {
938 vector<string> preset_out;
939 for (vector<Preset>::iterator pi = presets.begin(); pi < presets.end() - 1; pi++)
940 preset_out.push_back (string_printf ("%03d:%03d %s", pi->bank, pi->preset, pi->name.c_str()));
941
942 // FIXME: check_import (*pi).c_str()
943
944 sort (preset_out.begin(), preset_out.end());
945 for (vector<string>::iterator poi = preset_out.begin(); poi != preset_out.end(); poi++)
946 printf ("%s\n", poi->c_str());
947 }
948
949 void
run_all(vector<string> & commands,const string & name,size_t max_jobs)950 run_all (vector<string>& commands, const string& name, size_t max_jobs)
951 {
952 printf ("Running %s commands...\n", name.c_str());
953 JobQueue job_queue (max_jobs);
954 for (vector<string>::iterator ci = commands.begin(); ci != commands.end(); ci++)
955 {
956 printf (" - %s\n", ci->c_str());
957 job_queue.run (*ci);
958 }
959 if (!job_queue.wait_for_all())
960 {
961 fprintf (stderr, "error executing %s commands\n", name.c_str());
962 }
963 }
964
965 void
make_mono_flat(WavSet & wav_set)966 make_mono_flat (WavSet& wav_set)
967 {
968 vector<WavSetWave> flat_waves;
969
970 map<int, string> wmap;
971
972 for (auto wave: wav_set.waves)
973 {
974 if (wave.channel == 0)
975 {
976 string& path = wmap[wave.midi_note];
977 if (path.empty())
978 {
979 path = wave.path;
980
981 WavSetWave new_wave;
982 new_wave.midi_note = wave.midi_note;
983 new_wave.path = wave.path;
984 new_wave.channel = wave.channel;
985 new_wave.velocity_range_min = 0;
986 new_wave.velocity_range_max = 127;
987
988 flat_waves.push_back (new_wave);
989 }
990 else
991 assert (path == wave.path);
992 }
993 }
994 wav_set.waves = flat_waves;
995 }
996
997 int
import_preset(const string & import_name)998 import_preset (const string& import_name)
999 {
1000 map<string,bool> is_encoded;
1001
1002 struct LoopRange
1003 {
1004 double start = -1;
1005 double end = -1;
1006 };
1007 map<string,LoopRange> loop_range;
1008
1009 for (vector<Preset>::iterator pi = presets.begin(); pi != presets.end(); pi++)
1010 {
1011 if (pi->name == import_name)
1012 {
1013 printf ("importing preset %s\n", import_name.c_str());
1014
1015 string output_filename = options.output_filename;
1016 if (output_filename == "")
1017 {
1018 string preset_xname;
1019 for (string::const_iterator ni = import_name.begin(); ni != import_name.end(); ni++)
1020 {
1021 char c = *ni;
1022 if (isupper (c))
1023 c = tolower (c);
1024 else if (islower (c))
1025 ;
1026 else if (isdigit (c))
1027 ;
1028 else
1029 c = '_';
1030 preset_xname += c;
1031 }
1032 printf ("%s\n", preset_xname.c_str());
1033 output_filename = preset_xname + ".smset";
1034 }
1035
1036 WavSet wav_set;
1037
1038 vector<string> enc_commands, strip_commands;
1039 for (vector<Zone>::iterator preset_zi = pi->zones.begin(); preset_zi != pi->zones.end(); preset_zi++)
1040 {
1041 Zone& zone = *preset_zi;
1042 int inst_index = -1;
1043 for (vector<Generator>::iterator gi = zone.generators.begin(); gi != zone.generators.end(); gi++)
1044 {
1045 if (gi->generator == GEN_INSTRUMENT)
1046 {
1047 assert (inst_index == -1);
1048 inst_index = gi->amount;
1049 }
1050 }
1051 int vr_min = 0, vr_max = 127;
1052 const Generator *gp = find_gen (GEN_VELOCITY_RANGE, zone.generators);
1053 if (gp)
1054 {
1055 vr_min = gp->range_min;
1056 vr_max = gp->range_max;
1057 }
1058 printf (" * velocity range: %d..%d\n", vr_min, vr_max);
1059 // FIXME: this is a little sloppy - we should accept inst_index < 0 only for global zone
1060 if (inst_index >= 0)
1061 {
1062 Instrument instrument = instruments[inst_index];
1063 printf ("instrument name: %s (%zd zones)\n", instrument.name.c_str(), instrument.zones.size());
1064
1065 for (vector<Zone>::iterator zi = instrument.zones.begin(); zi != instrument.zones.end(); zi++)
1066 {
1067 const size_t zone_index = zi - instrument.zones.begin();
1068
1069 printf ("zone %zd:\n", zone_index);
1070
1071 int root_key = -1;
1072 const Generator *gi = find_gen (GEN_ROOT_KEY, zi->generators);
1073 if (gi)
1074 root_key = gi->amount;
1075
1076 int sample_modes = 0;
1077 gi = find_gen (GEN_SAMPLE_MODES, zi->generators);
1078 if (gi)
1079 sample_modes = gi->amount;
1080
1081 int channel = 0;
1082 gi = find_gen (GEN_PAN, zi->generators);
1083 if (gi)
1084 {
1085 assert (gi->amount == -500 || gi->amount == 500);
1086
1087 if (gi->amount == -500)
1088 channel = 0;
1089 else if (gi->amount == 500)
1090 channel = 1;
1091 else
1092 assert (false);
1093 }
1094
1095 gi = find_gen (GEN_SAMPLE, zi->generators);
1096 if (gi)
1097 {
1098 size_t id = gi->amount;
1099 assert (id >= 0 && id < samples.size());
1100 int midi_note = (root_key >= 0) ? root_key : samples[id].origpitch;
1101
1102 if (options.midi_note == -1 || (midi_note == options.midi_note))
1103 {
1104 printf (" sample %s orig_pitch %d root_key %d => midi_note %d\n", samples[id].name.c_str(), samples[id].origpitch, root_key, midi_note);
1105
1106 string filename = string_printf ("sample%zd-%d.wav", id, midi_note);
1107 string smname = string_printf ("sample%zd-%d.sm", id, midi_note);
1108
1109 if (!is_encoded[smname])
1110 {
1111 vector<float> padded_sample;
1112 size_t padded_len;
1113 size_t loop_shift = 0.1 * samples[id].srate; // 100 ms loop shift
1114 string loop_args;
1115 if (sample_modes & 1)
1116 {
1117 loop_args += " --loop-type loop-time-forward";
1118 loop_args += string_printf (" --loop-start %zd",
1119 samples[id].startloop - samples[id].start +
1120 loop_shift);
1121 loop_args += string_printf (" --loop-end %zd",
1122 samples[id].endloop - samples[id].start +
1123 loop_shift);
1124
1125 // store loop range for SpectMorph::Instrument
1126 loop_range[filename].start = (samples[id].startloop - samples[id].start + loop_shift) * 1000.0 / samples[id].srate;
1127 loop_range[filename].end = (samples[id].endloop - samples[id].start + loop_shift) * 1000.0 / samples[id].srate;
1128
1129 // 200 ms padding at the end of the loop, to ensure that silence after sample
1130 // is not encoded by encoder
1131 padded_len = samples[id].end - samples[id].start + 0.2 * samples[id].srate;
1132 for (size_t i = 0; i < padded_len; i++)
1133 {
1134 size_t pos = i + samples[id].start;
1135 while (pos >= (size_t) samples[id].endloop)
1136 pos -= samples[id].endloop - samples[id].startloop;
1137 padded_sample.push_back (sample_data[pos]);
1138 }
1139 }
1140 else
1141 {
1142 // no padding
1143 padded_len = samples[id].end - samples[id].start;
1144 padded_sample.assign (&sample_data[samples[id].start], &sample_data[samples[id].end]);
1145 }
1146 assert (padded_len == padded_sample.size());
1147 WavData wav_data (padded_sample, 1, samples[id].srate, 16);
1148 if (!wav_data.save (filename))
1149 {
1150 fprintf (stderr, "%s: export to file %s failed: %s\n", options.program_name.c_str(), filename.c_str(), wav_data.error_blurb());
1151 exit (1);
1152 }
1153
1154 string import_args = options.fast_import ? "--no-attack -O0" : "-O1";
1155 if (options.config_filename != "")
1156 import_args += " --config " + options.config_filename;
1157
1158 enc_commands.push_back (
1159 string_printf ("%s -m %d %s %s %s %s", options.smenc.c_str(),
1160 midi_note, import_args.c_str(),
1161 filename.c_str(), smname.c_str(), loop_args.c_str()));
1162 if (!options.debug)
1163 strip_commands.push_back (
1164 string_printf ("smstrip --keep-samples %s", smname.c_str()));
1165
1166 is_encoded[smname] = true;
1167 }
1168 WavSetWave new_wave;
1169 new_wave.midi_note = midi_note;
1170 new_wave.channel = channel;
1171 new_wave.velocity_range_min = vr_min;
1172 new_wave.velocity_range_max = vr_max;
1173
1174 if (options.sminst)
1175 new_wave.path = filename;
1176 else
1177 new_wave.path = smname;
1178
1179 wav_set.waves.push_back (new_wave);
1180 }
1181 }
1182 }
1183 }
1184 }
1185 if (options.sminst)
1186 {
1187 make_mono_flat (wav_set);
1188
1189 SpectMorph::Instrument sminst;
1190
1191 for (auto w : wav_set.waves)
1192 {
1193 string path = get_current_dir() + "/" + w.path;
1194
1195 SpectMorph::Sample *sample;
1196 SpectMorph::Error error = sminst.add_sample (path, &sample);
1197 if (sample)
1198 {
1199 sample->set_midi_note (w.midi_note);
1200
1201 auto r = loop_range[w.path];
1202 if (r.start >= 0 && r.end >= 0)
1203 {
1204 sample->set_loop (SpectMorph::Sample::Loop::FORWARD);
1205 sample->set_marker (SpectMorph::MARKER_LOOP_START, r.start);
1206 sample->set_marker (SpectMorph::MARKER_LOOP_END, r.end);
1207 }
1208 }
1209 else
1210 {
1211 fprintf (stderr, "%s: loading file '%s' failed: %s\n", options.program_name.c_str(), w.path.c_str(), error.message());
1212 exit (1);
1213 }
1214 }
1215 sminst.save (output_filename);
1216 }
1217 else
1218 {
1219 run_all (enc_commands, "Encoder", options.max_jobs);
1220 run_all (strip_commands, "Strip", options.max_jobs);
1221
1222 if (options.mono_flat)
1223 make_mono_flat (wav_set);
1224
1225 wav_set.save (output_filename);
1226 xsystem (string_printf ("smwavset link %s", output_filename.c_str()));
1227 }
1228 }
1229 }
1230 return 0;
1231 }
1232
1233 void
dump(const string & preset_name="")1234 dump (const string& preset_name = "")
1235 {
1236 set<int> dump_instr;
1237 set<int> dump_sample;
1238
1239 for (vector<Preset>::iterator pi = presets.begin(); pi != presets.end(); pi++)
1240 {
1241 if (pi->name == preset_name || preset_name.empty())
1242 {
1243 printf ("PRESET %s\n", pi->name.c_str());
1244 for (vector<Zone>::iterator zi = pi->zones.begin(); zi != pi->zones.end(); zi++)
1245 {
1246 const size_t zone_index = zi - pi->zones.begin();
1247 printf (" Zone #%zd\n", zone_index);
1248 for (vector<Generator>::const_iterator gi = zi->generators.begin();
1249 gi != zi->generators.end(); gi++)
1250 {
1251 const size_t generator_index = gi - zi->generators.begin();
1252 printf (" Generator #%zd: %d (%s)\n", generator_index, gi->generator, gen2name (gi->generator));
1253 if (gi->generator == GEN_INSTRUMENT)
1254 dump_instr.insert (gi->amount);
1255 }
1256 }
1257 }
1258 }
1259 for (vector<Instrument>::iterator ii = instruments.begin(); ii != instruments.end(); ii++)
1260 {
1261 size_t inr = ii - instruments.begin();
1262 if (dump_instr.count (inr))
1263 {
1264 printf ("INSTRUMENT %s\n", ii->name.c_str());
1265 for (vector<Zone>::iterator zi = ii->zones.begin(); zi != ii->zones.end(); zi++)
1266 {
1267 const size_t zone_index = zi - ii->zones.begin();
1268 printf (" Zone #%zd\n", zone_index);
1269 for (vector<Generator>::const_iterator gi = zi->generators.begin();
1270 gi != zi->generators.end(); gi++)
1271 {
1272 const size_t generator_index = gi - zi->generators.begin();
1273 printf (" Generator #%zd: %d (%s)\n", generator_index, gi->generator, gen2name (gi->generator));
1274 printf (" amount %d\n", gi->amount);
1275
1276 if (gi->generator == GEN_SAMPLE)
1277 dump_sample.insert (gi->amount);
1278 }
1279 }
1280 }
1281 }
1282 for (vector<Sample>::iterator si = samples.begin(); si != samples.end(); si++)
1283 {
1284 size_t snr = si - samples.begin();
1285 if (dump_sample.count (snr))
1286 {
1287 printf ("Sample %s:\n", si->name.c_str());
1288 printf (" Length: %d\n", si->end - si->start);
1289 printf (" Loop : %d..%d\n", si->startloop - si->start, si->endloop - si->start);
1290 printf (" SRate : %d\n", si->srate);
1291 }
1292 }
1293 }
1294
1295 int
main(int argc,char ** argv)1296 main (int argc, char **argv)
1297 {
1298 Main main (&argc, &argv);
1299 options.parse (&argc, &argv);
1300
1301 if (options.command == Options::LIST)
1302 {
1303 assert (argc == 2);
1304 if (read_sf2 (argv[1]) != 0)
1305 {
1306 printf ("can't load sf2: %s\n", argv[1]);
1307 return 1;
1308 }
1309 list_sf2();
1310 }
1311 else if (options.command == Options::IMPORT)
1312 {
1313 assert (argc == 3);
1314 if (read_sf2 (argv[1]) != 0)
1315 {
1316 printf ("can't load sf2: %s\n", argv[1]);
1317 return 1;
1318 }
1319 if (import_preset (argv[2]) != 0)
1320 {
1321 printf ("can't import preset: %s\n", argv[2]);
1322 return 1;
1323 }
1324 }
1325 else if (options.command == Options::DUMP)
1326 {
1327 assert (argc == 2 || argc == 3);
1328
1329 if (read_sf2 (argv[1]) != 0)
1330 {
1331 printf ("can't load sf2: %s\n", argv[1]);
1332 return 1;
1333 }
1334
1335 if (argc == 2)
1336 dump();
1337 else
1338 dump (argv[2]);
1339 }
1340 else
1341 {
1342 printf ("You need to specify a command (import, list, dump).\n\n");
1343 Options::print_usage();
1344 exit (1);
1345 }
1346
1347 return 0;
1348 }
1349