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