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