1 /*
2  * liquidsfz - sfz sampler
3  *
4  * Copyright (C) 2019  Stefan Westerfeld
5  *
6  * This library is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published by the
8  * Free Software Foundation; either version 2.1 of the License, or (at your
9  * option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
14  * for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this library; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
19  */
20 
21 #include "loader.hh"
22 #include "synth.hh"
23 #include "hydrogenimport.hh"
24 
25 #include <algorithm>
26 #include <regex>
27 
28 #include <assert.h>
29 
30 using std::string;
31 using std::vector;
32 using std::regex;
33 using std::regex_replace;
34 
35 using namespace LiquidSFZInternal;
36 
37 static string
strip_spaces(const string & s)38 strip_spaces (const string& s)
39 {
40   static const regex lws_re ("^\\s*");
41   static const regex tws_re ("\\s*$");
42 
43   string r = regex_replace (s, tws_re, "");
44   return regex_replace (r, lws_re, "");
45 }
46 
47 LoopMode
convert_loop_mode(const string & l)48 Loader::convert_loop_mode (const string& l)
49 {
50   if (l == "no_loop")
51     return LoopMode::NONE;
52   else if (l == "one_shot")
53     return LoopMode::ONE_SHOT;
54   else if (l == "loop_continuous")
55     return LoopMode::CONTINUOUS;
56   else if (l == "loop_sustain")
57     return LoopMode::SUSTAIN;
58   synth_->warning ("%s unknown loop mode: %s\n", location().c_str(), l.c_str());
59   return LoopMode::NONE;
60 }
61 
62 OffMode
convert_off_mode(const string & m)63 Loader::convert_off_mode (const string& m)
64 {
65   if (m == "fast")
66     return OffMode::FAST;
67   else if (m == "normal")
68     return OffMode::NORMAL;
69   else if (m == "time")
70     return OffMode::TIME;
71   synth_->warning ("%s unknown off mode: %s\n", location().c_str(), m.c_str());
72   return OffMode::FAST;
73 }
74 
75 XFCurve
convert_xfcurve(const string & c)76 Loader::convert_xfcurve (const string& c)
77 {
78   if (c == "power")
79     return XFCurve::POWER;
80   else if (c == "gain")
81     return XFCurve::GAIN;
82   synth_->warning ("%s unknown crossfade curve: %s\n", location().c_str(), c.c_str());
83   return XFCurve::POWER;
84 }
85 
86 Filter::Type
convert_filter_type(const string & f)87 Loader::convert_filter_type (const string& f)
88 {
89   Filter::Type type = Filter::type_from_string (f);
90   if (type != Filter::Type::NONE)
91     return type;
92 
93   synth_->warning ("%s unsupported filter type: %s\n", location().c_str(), f.c_str());
94   return Filter::Type::NONE;
95 }
96 
97 int
convert_wave(const string & w)98 Loader::convert_wave (const string& w)
99 {
100   int wave = convert_int (w);
101   if (LFOGen::supports_wave (wave))
102     return wave;
103 
104   synth_->warning ("%s unsupported lfo wave type: %s\n", location().c_str(), w.c_str());
105   return 0;
106 }
107 
108 bool
split_sub_key(const string & key,const string & start,int & sub_key)109 Loader::split_sub_key (const string& key, const string& start, int& sub_key)
110 {
111   if (!starts_with (key, start))
112     return false;
113   if (key.length() <= start.length())
114     return false;
115 
116   string subkey_str = key.substr (start.length());
117   for (auto c : subkey_str)
118     if (!isdigit (c))
119       return false;
120 
121   sub_key = convert_int (subkey_str);
122   return true;
123 }
124 
125 XFCC&
search_xfcc(vector<XFCC> & xfcc_vec,int cc,int def)126 Loader::search_xfcc (vector<XFCC>& xfcc_vec, int cc, int def)
127 {
128   for (auto& xfcc : xfcc_vec)
129     {
130       if (xfcc.cc == cc)
131         return xfcc;
132     }
133   update_cc_info (cc);
134   XFCC xfcc;
135   xfcc.cc = cc;
136   xfcc.lo = def;
137   xfcc.hi = def;
138   return xfcc_vec.emplace_back (xfcc);
139 }
140 
141 CCInfo&
update_cc_info(int cc)142 Loader::update_cc_info (int cc)
143 {
144   for (auto& cc_info : cc_list)
145     {
146       if (cc_info.cc == cc)
147         return cc_info;
148     }
149   CCInfo cc_info;
150   cc_info.cc = cc;
151   return cc_list.emplace_back (cc_info);
152 }
153 
154 KeyInfo&
update_key_info(int key)155 Loader::update_key_info (int key)
156 {
157   KeyInfo& key_info = key_map[key];
158   key_info.key = key;
159   return key_info;
160 }
161 
162 bool
parse_eg_param(const string & eg,EGParam & amp_param,const std::string & key,const std::string & value,const std::string & param_str)163 Loader::parse_eg_param (const string& eg, EGParam& amp_param, const std::string& key, const std::string& value, const std::string& param_str)
164 {
165   string prefix = eg + "_";
166 
167   if (key == prefix + param_str) // *eg_attack,...
168     {
169       amp_param.base = convert_float (value);
170       return true;
171     }
172   if (key == prefix + "vel2" + param_str) // *eg_vel2attack,...
173     {
174       amp_param.vel2 = convert_float (value);
175       return true;
176     }
177   int sub_key;
178   if (split_sub_key (key, prefix + param_str + "cc", sub_key)    // *eg_attackccN,...
179   ||  split_sub_key (key, prefix + param_str + "_oncc", sub_key)) // *eg_attack_onccN,...
180     {
181       amp_param.cc_vec.set (sub_key, convert_float (value));
182       update_cc_info (sub_key);
183       return true;
184     }
185   if (split_sub_key (key, prefix + param_str + "_curvecc", sub_key)) // *eg_attack_curveccN,...
186     {
187       amp_param.cc_vec.set_curvecc (sub_key, convert_int (value));
188       update_cc_info (sub_key);
189       return true;
190     }
191   return false;
192 }
193 
194 bool
parse_ampeg_param(EGParam & amp_param,const string & key,const string & value,const string & param_str)195 Loader::parse_ampeg_param (EGParam& amp_param, const string& key, const string& value, const string& param_str)
196 {
197   return parse_eg_param ("ampeg", amp_param, key, value, param_str);
198 }
199 
200 bool
parse_fileg_param(EGParam & amp_param,const string & key,const string & value,const string & param_str)201 Loader::parse_fileg_param (EGParam& amp_param, const string& key, const string& value, const string& param_str)
202 {
203   return parse_eg_param ("fileg", amp_param, key, value, param_str);
204 }
205 
206 int
find_unused_lfo_id(Region & region)207 Loader::find_unused_lfo_id (Region& region)
208 {
209   for (int id = 1 ;; id++)
210     {
211       bool used = false;
212 
213       for (size_t i = 0; i < region.lfos.size(); i++)
214         if (region.lfos[i].id == id)
215           used = true;
216 
217       if (!used)
218         return id;
219     }
220 }
221 
222 int
lfo_index_by_id(Region & region,int id)223 Loader::lfo_index_by_id (Region& region, int id)
224 {
225   /* find existing LFO parameters */
226   for (size_t i = 0; i < region.lfos.size(); i++)
227     if (region.lfos[i].id == id)
228       return i;
229 
230   /* create new LFO with this id */
231   LFOParams lfo_params;
232   lfo_params.id = id;
233   region.lfos.push_back (lfo_params);
234 
235   return region.lfos.size() - 1;
236 }
237 
238 int
lfo_mod_index_by_dest_id(Region & region,int l,int dest_id)239 Loader::lfo_mod_index_by_dest_id (Region& region, int l, int dest_id)
240 {
241   /* search existing mod by id */
242   int to_index = lfo_index_by_id (region, dest_id);
243   for (size_t i = 0; i < region.lfos[l].lfo_mods.size(); i++)
244     if (region.lfos[l].lfo_mods[i].to_index == to_index)
245       return i;
246 
247   /* create new lfo_mod if necessary */
248   LFOParams::LFOMod lfo_mod;
249   lfo_mod.to_index = to_index;
250   region.lfos[l].lfo_mods.push_back (lfo_mod);
251 
252   return region.lfos[l].lfo_mods.size() - 1;
253 }
254 
255 bool
parse_freq_cc_lfo(Region & region,int l,const string & lfo_key,const string & value)256 Loader::parse_freq_cc_lfo (Region& region, int l, const string& lfo_key, const string& value)
257 {
258   /* parse opcodes like "lfo1_freq_lfo6_oncc1=3" */
259   std::smatch sm;
260 
261   static const regex lfo_mod_re ("freq_lfo([0-9]+)(\\S+)");
262   if (!regex_match (lfo_key, sm, lfo_mod_re))
263     return false;
264 
265   int dest_lfo_id = convert_int (sm[1].str());
266   int lfo_mod_index = lfo_mod_index_by_dest_id (region, l, dest_lfo_id);
267 
268   return parse_cc (sm[2].str(), value, region.lfos[l].lfo_mods[lfo_mod_index].lfo_freq_cc, "_*");
269 }
270 
271 bool
parse_lfo_param(Region & region,const string & key,const string & value)272 Loader::parse_lfo_param (Region& region, const string& key, const string& value)
273 {
274   if (!starts_with (key, "lfo"))
275     return false;
276 
277   static const regex lfo_re ("lfo([0-9]+)_(\\S+)");
278   std::smatch sm;
279   if (!regex_match (key, sm, lfo_re))
280     return false;
281 
282   int    l = lfo_index_by_id (region, convert_int (sm[1].str()));
283   string lfo_key = sm[2].str();
284 
285   /* process opcodes */
286   int sub_key;
287 
288   if (lfo_key == "freq")
289     region.lfos[l].freq = convert_float (value);
290   else if (lfo_key == "wave")
291     region.lfos[l].wave = convert_wave (value);
292   else if (lfo_key == "phase")
293     region.lfos[l].phase = convert_float (value);
294   else if (lfo_key == "delay")
295     region.lfos[l].delay = convert_float (value);
296   else if (lfo_key == "fade")
297     region.lfos[l].fade = convert_float (value);
298   else if (lfo_key == "pitch")
299     region.lfos[l].pitch = convert_float (value);
300   else if (lfo_key == "volume")
301     region.lfos[l].volume = convert_float (value);
302   else if (lfo_key == "cutoff")
303     region.lfos[l].cutoff = convert_float (value);
304   else if (split_sub_key (lfo_key, "freq_lfo", sub_key))
305     {
306       int lfo_mod_index = lfo_mod_index_by_dest_id (region, l, sub_key);
307 
308       region.lfos[l].lfo_mods[lfo_mod_index].lfo_freq = convert_float (value);
309     }
310   else if (parse_cc (lfo_key, value, region.lfos[l].freq_cc,    "freq_*")
311        ||  parse_cc (lfo_key, value, region.lfos[l].phase_cc,   "phase_*")
312        ||  parse_cc (lfo_key, value, region.lfos[l].delay_cc,   "delay_*")
313        ||  parse_cc (lfo_key, value, region.lfos[l].fade_cc,    "fade_*")
314        ||  parse_cc (lfo_key, value, region.lfos[l].pitch_cc,   "pitch_*")
315        ||  parse_cc (lfo_key, value, region.lfos[l].volume_cc,  "volume_*")
316        ||  parse_cc (lfo_key, value, region.lfos[l].cutoff_cc,  "cutoff_*"))
317     {
318       // actual value conversion is performed by parse_cc
319     }
320   else if (parse_freq_cc_lfo (region, l, lfo_key, value))
321     {
322       // actual value conversion is performed by parse_freq_cc_lfo
323     }
324   else
325     return false;
326 
327   return true;
328 }
329 
330 bool
parse_simple_lfo_param(Region & region,const string & type,SimpleLFO & lfo,const string & key,const string & value)331 Loader::parse_simple_lfo_param (Region& region, const string& type, SimpleLFO& lfo, const string& key, const string& value)
332 {
333   int sub_key;
334 
335   if (key == type + "freq")
336     lfo.freq = convert_float (value);
337   else if (key == type + "depth")
338     lfo.depth = convert_float (value);
339   else if (key == type + "fade")
340     lfo.fade = convert_float (value);
341   else if (key == type + "delay")
342     lfo.delay = convert_float (value);
343   else if (split_sub_key (key, type + "freqcc", sub_key))
344     {
345       lfo.freq_cc.set (sub_key, convert_float (value));
346       update_cc_info (sub_key);
347     }
348   else if (split_sub_key (key, type + "depthcc", sub_key))
349     {
350       lfo.depth_cc.set (sub_key, convert_float (value));
351       update_cc_info (sub_key);
352     }
353   else
354     return false;
355 
356   lfo.used = true;
357   return true;
358 }
359 
360 bool
parse_cc(const std::string & key,const std::string & value,CCParamVec & ccvec,const std::vector<std::string> & opcodes)361 Loader::parse_cc (const std::string& key, const std::string& value, CCParamVec& ccvec, const std::vector<std::string>& opcodes)
362 {
363   for (auto opcode : opcodes)
364     {
365       int sub_key;
366 
367       if (ends_with (opcode, "_*"))
368         {
369           opcode.pop_back();
370           if (parse_cc (key, value, ccvec, opcode + "cc", opcode + "oncc", opcode + "curvecc"))
371             return true;
372         }
373       else if (split_sub_key (key, opcode, sub_key))
374         {
375           if (ends_with (opcode, "_cc") || ends_with (opcode, "_oncc"))
376             {
377               ccvec.set (sub_key, convert_float (value));
378               update_cc_info (sub_key);
379               return true;
380             }
381           else if (ends_with (opcode, "_curvecc"))
382             {
383               ccvec.set_curvecc (sub_key, convert_int (value));
384               update_cc_info (sub_key);
385               return true;
386             }
387         }
388     }
389   return false;
390 }
391 
392 void
set_key_value(const string & key,const string & value)393 Loader::set_key_value (const string& key, const string& value)
394 {
395   if (in_control)
396     {
397       set_key_value_control (key, value);
398       return;
399     }
400   else if (in_curve)
401     {
402       set_key_value_curve (key, value);
403       return;
404     }
405   /* handle global, group and region levels */
406   Region *region_ptr = nullptr;
407   switch (region_type)
408     {
409       case RegionType::GLOBAL:  region_ptr = &active_global;
410                                 break;
411       case RegionType::MASTER:  region_ptr = &active_master;
412                                 break;
413       case RegionType::GROUP:   region_ptr = &active_group;
414                                 break;
415       case RegionType::REGION:  region_ptr = &active_region;
416                                 break;
417       default:                  return;
418     }
419 
420   Region& region = *region_ptr;
421   int sub_key;
422   synth_->debug ("+++ '%s' = '%s'\n", key.c_str(), value.c_str());
423   if (key == "sample")
424     {
425       // on unix, convert \-seperated filename to /-separated filename
426       string native_filename = value;
427       std::replace (native_filename.begin(), native_filename.end(), '\\', PATH_SEPARATOR);
428 
429       string path = sample_path;
430       if (control.default_path != "")
431         path = path_join (path, control.default_path);
432 
433       path = path_join (path, native_filename);
434       region.sample = path_absolute (path);
435       region.location = location();
436     }
437   else if (key == "lokey")
438     region.lokey = convert_key (value);
439   else if (key == "hikey")
440     region.hikey = convert_key (value);
441   else if (key == "key")
442     {
443       const int k = convert_key (value);
444       region.lokey = k;
445       region.hikey = k;
446       region.pitch_keycenter = k;
447     }
448   else if (key == "lovel")
449     region.lovel = convert_key (value);
450   else if (key == "hivel")
451     region.hivel = convert_key (value);
452   else if (key == "pitch_keycenter")
453     region.pitch_keycenter = convert_key (value);
454   else if (key == "pitch_keytrack")
455     region.pitch_keytrack = convert_int (value);
456   else if (key == "lorand")
457     region.lorand = convert_float (value);
458   else if (key == "hirand")
459     region.hirand = convert_float (value);
460   else if (key == "loop_mode" || key == "loopmode")
461     {
462       region.loop_mode = convert_loop_mode (value);
463       region.have_loop_mode = true;
464     }
465   else if (key == "loop_start" || key == "loopstart")
466     {
467       region.loop_start = convert_int (value);
468       region.have_loop_start = true;
469     }
470   else if (key == "loop_end" || key == "loopend")
471     {
472       region.loop_end = convert_int (value);
473       region.have_loop_end = true;
474     }
475   else if (split_sub_key (key, "locc", sub_key))
476     {
477       int cc = sub_key;
478       if (cc >= 0 && cc <= 127)
479         {
480           region.locc[cc] = convert_int (value);
481           update_cc_info (cc);
482         }
483     }
484   else if (split_sub_key (key, "hicc", sub_key))
485     {
486       int cc = sub_key;
487       if (cc >= 0 && cc <= 127)
488         {
489           region.hicc[cc] = convert_int (value);
490           update_cc_info (cc);
491         }
492     }
493   else if (starts_with (key, "on_locc") || starts_with (key, "on_hicc"))
494     region.trigger = Trigger::CC;
495   else if (key == "trigger")
496     region.trigger = convert_trigger (value);
497   else if (key == "seq_length")
498     region.seq_length = convert_int (value);
499   else if (key == "seq_position")
500     region.seq_position = convert_int (value);
501   else if (parse_ampeg_param (region.ampeg_delay, key, value, "delay") ||
502            parse_ampeg_param (region.ampeg_attack, key, value, "attack") ||
503            parse_ampeg_param (region.ampeg_hold, key, value, "hold") ||
504            parse_ampeg_param (region.ampeg_decay, key, value, "decay") ||
505            parse_ampeg_param (region.ampeg_sustain, key, value, "sustain") ||
506            parse_ampeg_param (region.ampeg_release, key, value, "release"))
507     {
508       // actual value conversion is performed by parse_ampeg_param
509     }
510   else if (parse_fileg_param (region.fileg_depth, key, value, "depth") ||
511            parse_fileg_param (region.fileg_delay, key, value, "delay") ||
512            parse_fileg_param (region.fileg_attack, key, value, "attack") ||
513            parse_fileg_param (region.fileg_hold, key, value, "hold") ||
514            parse_fileg_param (region.fileg_decay, key, value, "decay") ||
515            parse_fileg_param (region.fileg_sustain, key, value, "sustain") ||
516            parse_fileg_param (region.fileg_release, key, value, "release"))
517     {
518       // actual value conversion is performed by parse_fileg_param
519     }
520   else if (split_sub_key (key, "amp_velcurve_", sub_key))
521     region.amp_velcurve.set (sub_key, convert_float (value));
522   else if (key == "volume")
523     region.volume = convert_float (value);
524   else if (key == "amplitude")
525     region.amplitude = convert_float (value);
526   else if (key == "amp_veltrack")
527     region.amp_veltrack = convert_float (value);
528   else if (key == "amp_random")
529     region.amp_random = convert_float (value);
530   else if (key == "pan")
531     region.pan = convert_float (value);
532   else if (key == "rt_decay")
533     region.rt_decay = convert_float (value);
534   else if (key == "group")
535     region.group = convert_uint (value);
536   else if (key == "off_by" || key == "offby")
537     region.off_by = convert_uint (value);
538   else if (key == "off_mode")
539     region.off_mode = convert_off_mode (value);
540   else if (key == "off_time")
541     region.off_time = convert_float (value);
542   else if (key == "delay")
543     region.delay = convert_float (value);
544   else if (key == "offset")
545     region.offset = convert_uint (value);
546   else if (key == "offset_random")
547     region.offset_random = convert_uint (value);
548   else if (key == "sw_lokey")
549     region.sw_lokey = convert_key (value);
550   else if (key == "sw_hikey")
551     region.sw_hikey = convert_key (value);
552   else if (key == "sw_last")
553     region.sw_lolast = region.sw_hilast = convert_key (value);
554   else if (key == "sw_lolast")
555     region.sw_lolast = convert_key (value);
556   else if (key == "sw_hilast")
557     region.sw_hilast = convert_key (value);
558   else if (key == "sw_default")
559     region.sw_default = convert_key (value);
560   else if (key == "sw_label")
561     region.sw_label = value;
562   else if (key == "tune")
563     region.tune = convert_int (value);
564   else if (key == "transpose")
565     region.transpose = convert_int (value);
566   else if (key == "pitch_random")
567     region.pitch_random = convert_int (value);
568   else if (key == "bend_up")
569     region.bend_up = convert_int (value);
570   else if (key == "bend_down")
571     region.bend_down = convert_int (value);
572   else if (key == "cutoff")
573     region.fil.cutoff = convert_float (value);
574   else if (key == "cutoff2")
575     region.fil2.cutoff = convert_float (value);
576   else if (key == "resonance")
577     region.fil.resonance = convert_float (value);
578   else if (key == "resonance2")
579     region.fil2.resonance = convert_float (value);
580   else if (key == "fil_type")
581     region.fil.type = convert_filter_type (value);
582   else if (key == "fil2_type")
583     region.fil2.type = convert_filter_type (value);
584   else if (key == "fil_keytrack")
585     region.fil.keytrack = convert_int (value);
586   else if (key == "fil2_keytrack")
587     region.fil2.keytrack = convert_int (value);
588   else if (key == "fil_keycenter")
589     region.fil.keycenter = convert_key (value);
590   else if (key == "fil2_keycenter")
591     region.fil2.keycenter = convert_key (value);
592   else if (key == "fil_veltrack")
593     region.fil.veltrack = convert_int (value);
594   else if (key == "fil2_veltrack")
595     region.fil2.veltrack = convert_int (value);
596   else if (parse_cc (key, value, region.pan_cc,
597                      "pan_*")
598        ||  parse_cc (key, value, region.gain_cc,
599                      "gain_cc", // acts as alias
600                      "volume_*")
601        ||  parse_cc (key, value, region.amplitude_cc,
602                      "amplitude_*")
603        ||  parse_cc (key, value, region.tune_cc,
604                      "pitch_*", // sforzando supports both
605                      "tune_*")
606        ||  parse_cc (key, value, region.delay_cc,
607                      "delay_*")
608        ||  parse_cc (key, value, region.fil.cutoff_cc,
609                      "cutoff_*")
610        ||  parse_cc (key, value, region.fil2.cutoff_cc,
611                      "cutoff2_*")
612        ||  parse_cc (key, value, region.fil.resonance_cc,
613                      "resonance_*")
614        ||  parse_cc (key, value, region.fil2.resonance_cc,
615                      "resonance2_*")
616        ||  parse_cc (key, value, region.offset_cc,
617                      "offset_*"))
618     {
619       // actual value conversion is performed by parse_cc
620     }
621   else if (key == "xfin_lovel")
622     region.xfin_lovel = convert_int (value);
623   else if (key == "xfin_hivel")
624     region.xfin_hivel = convert_int (value);
625   else if (key == "xfout_lovel")
626     region.xfout_lovel = convert_int (value);
627   else if (key == "xfout_hivel")
628     region.xfout_hivel = convert_int (value);
629   else if (key == "xfin_lokey")
630     region.xfin_lokey = convert_key (value);
631   else if (key == "xfin_hikey")
632     region.xfin_hikey = convert_key (value);
633   else if (key == "xfout_lokey")
634     region.xfout_lokey = convert_key (value);
635   else if (key == "xfout_hikey")
636     region.xfout_hikey = convert_key (value);
637   else if (split_sub_key (key, "xfin_locc", sub_key))
638     {
639       XFCC& xfcc = search_xfcc (region.xfin_ccs, sub_key, 0);
640       xfcc.lo = convert_int (value);
641     }
642   else if (split_sub_key (key, "xfin_hicc", sub_key))
643     {
644       XFCC& xfcc = search_xfcc (region.xfin_ccs, sub_key, 0);
645       xfcc.hi = convert_int (value);
646     }
647   else if (split_sub_key (key, "xfout_locc", sub_key))
648     {
649       XFCC& xfcc = search_xfcc (region.xfout_ccs, sub_key, 127);
650       xfcc.lo = convert_int (value);
651     }
652   else if (split_sub_key (key, "xfout_hicc", sub_key))
653     {
654       XFCC& xfcc = search_xfcc (region.xfout_ccs, sub_key, 127);
655       xfcc.hi = convert_int (value);
656     }
657   else if (key == "xf_velcurve")
658     region.xf_velcurve = convert_xfcurve (value);
659   else if (key == "xf_keycurve")
660     region.xf_keycurve = convert_xfcurve (value);
661   else if (key == "xf_cccurve")
662     region.xf_cccurve = convert_xfcurve (value);
663   else if (parse_lfo_param (region, key, value))
664     {
665       // actual value conversion is performed by parse_lfo_param
666     }
667   else if (parse_simple_lfo_param (region, "pitchlfo_", region.pitchlfo, key, value)
668        ||  parse_simple_lfo_param (region, "amplfo_",   region.amplfo,   key, value)
669        ||  parse_simple_lfo_param (region, "fillfo_",   region.fillfo,   key, value))
670     {
671       // actual value conversion is performed by parse_simple_lfo_param
672     }
673   else
674     synth_->warning ("%s unsupported opcode '%s'\n", location().c_str(), key.c_str());
675 }
676 
677 void
set_key_value_control(const string & key,const string & value)678 Loader::set_key_value_control (const string& key, const string& value)
679 {
680   int sub_key;
681 
682   if (key == "default_path")
683     {
684       string native_path = value;
685       std::replace (native_path.begin(), native_path.end(), '\\', PATH_SEPARATOR);
686 
687       control.default_path = native_path;
688     }
689   else if (split_sub_key (key, "set_cc", sub_key))
690     {
691       SetCC set_cc;
692       set_cc.cc = sub_key;
693       set_cc.value = convert_int (value);
694       control.set_cc.push_back (set_cc);
695 
696       CCInfo& cc_info = update_cc_info (set_cc.cc);
697       cc_info.default_value = set_cc.value;
698     }
699   else if (split_sub_key (key, "set_hdcc", sub_key)
700        ||  split_sub_key (key, "set_realcc", sub_key))
701     {
702       /* we don't really support floating point CCs
703        * however we convert to ensure sane defaults for .sfz files using this opcode
704        */
705       SetCC set_cc;
706       set_cc.cc = sub_key;
707       set_cc.value = std::clamp<int> (lrint (convert_float (value) * 127), 0, 127);
708       control.set_cc.push_back (set_cc);
709 
710       CCInfo& cc_info = update_cc_info (set_cc.cc);
711       cc_info.default_value = set_cc.value;
712     }
713   else if (split_sub_key (key, "label_cc", sub_key))
714     {
715       CCInfo& cc_info = update_cc_info (sub_key);
716       cc_info.has_label = true;
717       cc_info.label = value;
718     }
719   else if (split_sub_key (key, "label_key", sub_key))
720     {
721       update_key_info (sub_key).label = value;
722     }
723   else
724     synth_->warning ("%s unsupported opcode '%s'\n", location().c_str(), key.c_str());
725 }
726 
727 void
set_key_value_curve(const string & key,const string & value)728 Loader::set_key_value_curve (const string& key, const string& value)
729 {
730   int sub_key;
731 
732   if (key == "curve_index")
733     {
734       int i = convert_int (value);
735 
736       if (i >= 0 && i < 256)
737         active_curve_section.curve_index = convert_int (value);
738       else
739         synth_->warning ("%s bad curve_index '%d' (should be in range [0,255])\n", location().c_str(), i);
740     }
741   else if (split_sub_key (key, "v", sub_key))
742     {
743       active_curve_section.curve.set (sub_key, convert_float (value));
744     }
745   else
746     synth_->warning ("%s unsupported opcode '%s'\n", location().c_str(), key.c_str());
747 }
748 
749 void
init_default_curves()750 Loader::init_default_curves()
751 {
752   curves.resize (7);
753 
754   curves[0].set (0,   0);
755   curves[0].set (127, 1);
756 
757   curves[1].set (0,  -1);
758   curves[1].set (127, 1);
759 
760   curves[2].set (0,   1);
761   curves[2].set (127, 0);
762 
763   curves[3].set (0,    1);
764   curves[3].set (127, -1);
765 
766   for (int v = 0; v < 128; v++)
767     {
768       curves[4].set (v, (v * v) / (127.0 * 127.0));   // volume curve
769       curves[5].set (v, sqrt (v / 127.0));            // xfin power curve
770       curves[6].set (v, sqrt ((127 - v) / 127.0));    // xfout power curve
771     }
772 }
773 
774 void
handle_tag(const std::string & tag)775 Loader::handle_tag (const std::string& tag)
776 {
777   synth_->debug ("+++ TAG %s\n", tag.c_str());
778 
779   /* if we are done building a region, store it */
780   if (tag == "region" || tag == "group" || tag == "master" || tag == "global")
781     if (!active_region.empty())
782       {
783         regions.push_back (active_region);
784         active_region = Region();
785       }
786 
787   if (!active_curve_section.empty())
788     {
789       add_curve (active_curve_section);
790       active_curve_section = CurveSection();
791     }
792 
793   in_control = false;
794   in_curve = false;
795   if (tag == "control")
796     {
797       in_control = true;
798       control = Control();
799     }
800   else if (tag == "curve")
801     {
802       in_curve = true;
803       active_curve_section = CurveSection();
804     }
805   else if (tag == "region")
806     {
807       /* inherit region parameters from parent region */
808       if (have_group)
809         active_region = active_group;
810       else if (have_master)
811         active_region = active_master;
812       else
813         active_region = active_global;
814 
815       region_type = RegionType::REGION;
816     }
817   else if (tag == "group")
818     {
819       /* inherit region parameters from parent region */
820       if (have_master)
821         active_group = active_master;
822       else
823         active_group = active_global;
824 
825       region_type = RegionType::GROUP;
826       have_group  = true;
827     }
828   else if (tag == "master")
829     {
830       /* inherit region parameters from parent region */
831       active_master = active_global;
832 
833       region_type = RegionType::MASTER;
834       have_group  = false;
835       have_master = true;
836     }
837   else if (tag == "global")
838     {
839       active_global = Region();
840 
841       region_type = RegionType::GLOBAL;
842       have_group  = false;
843       have_master = false;
844     }
845   else
846     synth_->warning ("%s unsupported tag '<%s>'\n", location().c_str(), tag.c_str());
847 }
848 
849 void
add_curve(const CurveSection & c)850 Loader::add_curve (const CurveSection& c)
851 {
852   if (c.curve_index < 0 || c.curve_index > 255)
853     return;
854 
855   if (curves.size() <= uint (c.curve_index))
856     curves.resize (c.curve_index + 1);
857 
858   curves[c.curve_index] = c.curve;
859 }
860 
861 static bool
load_file(FILE * file,vector<char> & contents)862 load_file (FILE *file, vector<char>& contents)
863 {
864   contents.clear();
865 
866   /* read file into memory */
867   char buffer[1024];
868 
869   size_t l;
870   while (!feof (file) && (l = fread (buffer, 1, sizeof (buffer), file)) > 0)
871     contents.insert (contents.end(), buffer, buffer + l);
872 
873   return !ferror (file);
874 }
875 
876 static string
line_lookahead(vector<char> & contents,size_t pos)877 line_lookahead (vector<char>& contents, size_t pos)
878 {
879   string result;
880   while (pos < contents.size() && (contents[pos] != '\n' && contents[pos] != '\r'))
881     result += contents[pos++];
882   return result;
883 }
884 
885 bool
find_variable(const string & line,Control::Define & out_define)886 Loader::find_variable (const string& line, Control::Define& out_define)
887 {
888   size_t best_len = string::npos;
889   for (const auto& define : control.defines)
890     {
891       if (starts_with (line, define.variable) && (define.variable.length() < best_len))
892         {
893           /* if there are multiple variable names that match, use the shortest one
894            * this seems to be what ARIA does in this case
895            */
896           best_len = define.variable.length();
897           out_define = define;
898         }
899     }
900   return (best_len != string::npos);
901 }
902 
903 bool
preprocess_file(const std::string & filename,vector<LineInfo> & lines,int level,const std::string & content_str)904 Loader::preprocess_file (const std::string& filename, vector<LineInfo>& lines, int level, const std::string& content_str)
905 {
906   vector<char> contents;
907 
908   if (content_str != "")
909     {
910       contents.insert (contents.begin(), content_str.begin(), content_str.end());
911     }
912   else
913     {
914       FILE *file = fopen (filename.c_str(), "r");
915       if (!file)
916         return false;
917 
918       bool read_ok = load_file (file, contents);
919       fclose (file);
920 
921       if (!read_ok)
922         return false;
923     }
924 
925   LineInfo line_info;
926   line_info.filename = filename;
927   line_info.number = 1;
928 
929   size_t i = 0;
930   while (i < contents.size())
931     {
932       char ch = contents[i];
933       char next = i + 1 < contents.size() ? contents[i + 1] : 0;
934       string line = line_lookahead (contents, i);
935 
936       static const regex define_re ("#define\\s+(\\$\\S+)\\s+(\\S+)(.*)");
937       static const regex include_re ("#include\\s+\"([^\"]*)\"(.*)");
938       std::smatch sm;
939       Control::Define define;
940 
941       if (ch == '/' && next == '*') /* block comment */
942         {
943           lines.push_back (line_info);
944           line_info.line = "";
945 
946           size_t j = i, end = 0;
947           while (j + 1 < contents.size()) /* search end of comment */
948             {
949               if (contents[j] == '\n')
950                 line_info.number++;
951 
952               if (contents[j] == '*' && contents[j + 1] == '/')
953                 {
954                   end = j + 2;
955                   break;
956                 }
957               j++;
958             }
959           if (!end)
960             {
961               synth_->error ("%s unterminated block comment\n", line_info.location().c_str());
962               return false;
963             }
964           i = end;
965         }
966       else if (ch == '/' && next == '/') /* line comment */
967         {
968           i += line.size();
969         }
970       else if (ch == '#' && regex_match (line, sm, define_re))
971         {
972           bool overwrite = false;
973           for (auto& old_def : control.defines)
974             {
975               if (old_def.variable == sm[1])
976                 {
977                   old_def.value = strip_spaces (sm[2]);
978                   overwrite = true;
979                 }
980             }
981           if (!overwrite)
982             {
983               Control::Define define;
984               define.variable = sm[1];
985               define.value    = strip_spaces (sm[2]);
986               control.defines.push_back (define);
987             }
988 
989           i += sm.length() - sm[3].length();
990         }
991       else if (ch == '#' && regex_match (line, sm, include_re))
992         {
993           /* if there is text before the #include statement, this needs to
994            * written to lines to preserve the order of the opcodes
995            *
996            * we don't bump the line number to allow text after the include
997            * to be on the same line
998            */
999           lines.push_back (line_info);
1000           line_info.line = "";
1001 
1002           string include_filename = path_absolute (path_join (sample_path, sm[1].str()));
1003 
1004           if (level < MAX_INCLUDE_DEPTH) // prevent infinite recursion for buggy .sfz
1005             {
1006               bool inc_ok = preprocess_file (include_filename, lines, level + 1);
1007               if (!inc_ok)
1008                 {
1009                   synth_->error ("%s unable to read #include '%s'\n", line_info.location().c_str(), include_filename.c_str());
1010                   return false;
1011                 }
1012             }
1013           else
1014             {
1015               synth_->error ("%s exceeded maximum include depth (%d) while processing #include '%s'\n",
1016                              line_info.location().c_str(), MAX_INCLUDE_DEPTH, include_filename.c_str());
1017               return false;
1018             }
1019           i += sm.length() - sm[2].length();
1020         }
1021       else if (ch == '$' && find_variable (line, define))
1022         {
1023           line_info.line += define.value;
1024           i += define.variable.size();
1025         }
1026       else if (ch == '\r')
1027         {
1028           i++; // ignore
1029         }
1030       else if (ch == '\n')
1031         {
1032           lines.push_back (line_info);
1033           line_info.number++;
1034           line_info.line = "";
1035           i++;
1036         }
1037       else
1038         {
1039           line_info.line += ch;
1040           i++;
1041         }
1042     }
1043   if (!line_info.line.empty())
1044     {
1045       lines.push_back (line_info);
1046     }
1047   return true;
1048 }
1049 
1050 void
convert_lfo(Region & region,SimpleLFO & simple_lfo,SimpleLFO::Type type)1051 Loader::convert_lfo (Region& region, SimpleLFO& simple_lfo, SimpleLFO::Type type)
1052 {
1053   int id = find_unused_lfo_id (region);
1054   int l = lfo_index_by_id (region, id);
1055 
1056   region.lfos[l].freq = simple_lfo.freq;
1057   region.lfos[l].fade = simple_lfo.fade;
1058   region.lfos[l].delay = simple_lfo.delay;
1059   region.lfos[l].freq_cc = simple_lfo.freq_cc;
1060   region.lfos[l].wave = 1; // sine
1061 
1062   switch (type)
1063   {
1064     case SimpleLFO::PITCH:
1065       region.lfos[l].pitch    = simple_lfo.depth;
1066       region.lfos[l].pitch_cc = simple_lfo.depth_cc;
1067       break;
1068     case SimpleLFO::AMP:
1069       region.lfos[l].volume    = simple_lfo.depth;
1070       region.lfos[l].volume_cc = simple_lfo.depth_cc;
1071       break;
1072     case SimpleLFO::FIL:
1073       region.lfos[l].cutoff    = simple_lfo.depth;
1074       region.lfos[l].cutoff_cc = simple_lfo.depth_cc;
1075       break;
1076   }
1077 }
1078 
1079 bool
parse(const string & filename,SampleCache & sample_cache)1080 Loader::parse (const string& filename, SampleCache& sample_cache)
1081 {
1082   init_default_curves();
1083 
1084   sample_path = path_dirname (filename);
1085 
1086   // read file
1087   vector<LineInfo> lines;
1088 
1089   HydrogenImport himport (synth_);
1090   if (himport.detect (filename))
1091     {
1092       string out;
1093       if (himport.parse (filename, out))
1094         {
1095           if (!preprocess_file (filename, lines, 0, out))
1096             {
1097               synth_->error ("error reading converted hydrogen drumkit '%s'\n", filename.c_str());
1098               return false;
1099             }
1100         }
1101       else
1102         {
1103           synth_->error ("error reading hydrogen drumkit '%s'\n", filename.c_str());
1104           return false;
1105         }
1106     }
1107   else
1108     {
1109       if (!preprocess_file (filename, lines, 0))
1110         {
1111           synth_->error ("error reading file '%s'\n", filename.c_str());
1112           return false;
1113         }
1114     }
1115 
1116   static const regex space_re ("\\s+(.*)");
1117   static const regex tag_re ("<([^>]*)>(.*)");
1118   static const regex key_val_re ("([a-z0-9_]+)=(\\S+)(.*)");
1119   for (auto line_info : lines)
1120     {
1121       current_line_info = line_info; // for error location reporting
1122 
1123       auto l = line_info.line;
1124       while (l.size())
1125         {
1126           std::smatch sm;
1127           //printf ("@%s@\n", l.c_str());
1128           if (regex_match (l, sm, space_re))
1129             {
1130               l = sm[1];
1131             }
1132           else if (regex_match (l, sm, tag_re))
1133             {
1134               handle_tag (sm[1].str());
1135               l = sm[2];
1136             }
1137           else if (regex_match (l, key_val_re))
1138             {
1139               /* we need to handle three cases to deal with values that may contain spaces:
1140                *
1141                * - value extends until end of line
1142                * - value is followed by <tag>
1143                * - value is followed by another opcode (foo=bar)
1144                */
1145               static const regex key_val_space_re_eol ("([a-z0-9_]+)=([^=<]+)");
1146               static const regex key_val_space_re_tag ("([a-z0-9_]+)=([^=<]+)(<.*)");
1147               static const regex key_val_space_re_eq ("([a-z0-9_]+)=([^=<]+)(\\s[a-z0-9_]+=.*)");
1148 
1149               if (regex_match (l, sm, key_val_space_re_eol))
1150                 {
1151                   set_key_value (sm[1].str(), strip_spaces (sm[2].str()));
1152                   l = "";
1153                 }
1154               else if (regex_match (l, sm, key_val_space_re_tag))
1155                 {
1156                   set_key_value (sm[1].str(), strip_spaces (sm[2].str()));
1157                   l = sm[3]; // parse rest
1158                 }
1159               else if (regex_match (l, sm, key_val_space_re_eq))
1160                 {
1161                   set_key_value (sm[1].str(), strip_spaces (sm[2].str()));
1162                   l = sm[3]; // parse rest
1163                 }
1164               else
1165                 {
1166                   synth_->error ("%s parse error in opcode parsing\n", location().c_str());
1167                   return false;
1168                 }
1169             }
1170           else
1171             {
1172               synth_->error ("%s toplevel parsing failed\n", location().c_str());
1173               return false;
1174             }
1175         }
1176     }
1177   if (!active_region.empty())
1178     regions.push_back (active_region);
1179 
1180   if (!active_curve_section.empty())
1181     add_curve (active_curve_section);
1182 
1183   synth_->progress (0);
1184   for (size_t i = 0; i < regions.size(); i++)
1185     {
1186       Region& region = regions[i];
1187 
1188       const auto cached_sample = sample_cache.load (region.sample);
1189       region.cached_sample = cached_sample;
1190 
1191       if (!cached_sample)
1192         synth_->warning ("%s: missing sample: '%s'\n", filename.c_str(), region.sample.c_str());
1193 
1194       if (cached_sample && cached_sample->loop)
1195         {
1196           /* if values have been given explicitely, keep them
1197            *   -> user can override loop settings from wav file (cached sample)
1198            */
1199           if (!region.have_loop_mode)
1200             region.loop_mode = LoopMode::CONTINUOUS;
1201 
1202           if (!region.have_loop_start)
1203             region.loop_start = cached_sample->loop_start;
1204 
1205           if (!region.have_loop_end)
1206             region.loop_end = cached_sample->loop_end;
1207         }
1208       if (region.fil.cutoff < 0) /* filter defaults to lpf_2p, but only if cutoff was found */
1209         region.fil.type = Filter::Type::NONE;
1210 
1211       if (region.fil2.cutoff < 0) /* filter 2 defaults to lpf_2p, but only if cutoff2 was found */
1212         region.fil2.type = Filter::Type::NONE;
1213 
1214       if (region.sw_lolast >= 0)
1215         region.switch_match = (region.sw_lolast <= region.sw_default && region.sw_hilast >= region.sw_default);
1216 
1217       curve_table.expand_curve (region.amp_velcurve);
1218 
1219       /* generate entries for regular notes */
1220       if (region.lokey > 0)
1221         for (int key = region.lokey; key <= region.hikey; key++)
1222           update_key_info (key).is_switch = false;
1223 
1224       /* generate entries for key switches */
1225       if (region.sw_lolast > 0)
1226         {
1227           for (int key = region.sw_lolast; key <= region.sw_hilast; key++)
1228             {
1229               KeyInfo& ki = update_key_info (key);
1230               ki.is_switch = true;
1231               if (region.sw_label != "")
1232                 ki.label = region.sw_label;
1233             }
1234         }
1235 
1236       /* update progress info */
1237       synth_->progress ((i + 1) * 100.0 / regions.size());
1238     }
1239   // generate final cc_list
1240   for (const auto& [key, key_info] : key_map)
1241     key_list.push_back (key_info);
1242 
1243   // generate final key_list
1244   std::sort (cc_list.begin(), cc_list.end(),
1245     [] (const CCInfo& a, const CCInfo& b) {
1246       return a.cc < b.cc;
1247     });
1248 
1249   // finalize curves
1250   for (auto& c : curves)
1251     curve_table.expand_curve (c);
1252 
1253   for (auto& region : regions)
1254     {
1255       // convert SFZ1 lfos to SFZ2 lfos
1256       convert_lfo (region, region.pitchlfo, SimpleLFO::PITCH);
1257       convert_lfo (region, region.amplfo, SimpleLFO::AMP);
1258       convert_lfo (region, region.fillfo, SimpleLFO::FIL);
1259 
1260       // find memory requirements for lfos
1261       limits.max_lfos = std::max (limits.max_lfos, region.lfos.size());
1262 
1263       size_t lfo_mods = 0;
1264       for (const auto& lfo : region.lfos)
1265         lfo_mods += lfo.lfo_mods.size();
1266 
1267       limits.max_lfo_mods = std::max (limits.max_lfo_mods, lfo_mods);
1268     }
1269 
1270   synth_->debug ("*** limits: max_lfos=%zd max_lfo_mods=%zd\n", limits.max_lfos, limits.max_lfo_mods);
1271   synth_->debug ("*** regions: %zd\n", regions.size());
1272   return true;
1273 }
1274