3#include "sound_engine.h"
11#define STRINGIFY(x) QUOTE(x)
14 const std::string kLinuxUserDataDirectory =
"~/.local/share/vital/";
15 const std::string kAvailablePacksFile =
"available_packs.json";
16 const std::string kInstalledPacksFile =
"packs.json";
19 StringArray date_tokens;
20 date_tokens.addTokens(
STRINGIFY(BUILD_DATE),
true);
21 if (date_tokens.size() != 5)
22 return Time::getCompilationDate();
24 int year = date_tokens[0].getIntValue();
25 int month = date_tokens[1].getIntValue() - 1;
26 int day = date_tokens[2].getIntValue();
27 int hour = date_tokens[3].getIntValue();
28 int minute = date_tokens[4].getIntValue();
30 return Time(year, month, day, hour, minute);
45 if (data.count(field) == 0)
48 MemoryOutputStream decoded;
49 std::string wave_data = data[field];
50 Base64::convertFromBase64(decoded, wave_data);
51 int size =
static_cast<int>(decoded.getDataSize()) /
sizeof(float);
52 std::unique_ptr<float[]> float_data = std::make_unique<float[]>(size);
53 memcpy(float_data.get(), decoded.getData(), size *
sizeof(
float));
54 std::unique_ptr<int16_t[]> pcm_data = std::make_unique<int16_t[]>(size);
57 String encoded = Base64::toBase64(pcm_data.get(),
sizeof(int16_t) * size);
58 data[field] = encoded.toStdString();
62 if (data.count(field) == 0)
65 MemoryOutputStream decoded;
66 std::string wave_data = data[field];
67 Base64::convertFromBase64(decoded, wave_data);
68 int size =
static_cast<int>(decoded.getDataSize()) /
sizeof(int16_t);
69 std::unique_ptr<int16_t[]> pcm_data = std::make_unique<int16_t[]>(size);
70 memcpy(pcm_data.get(), decoded.getData(), size *
sizeof(int16_t));
71 std::unique_ptr<float[]> float_data = std::make_unique<float[]>(size);
74 String encoded = Base64::toBase64(float_data.get(),
sizeof(
float) * size);
75 data[field] = encoded.toStdString();
81 for (
auto& control : controls)
82 settings_data[control.first] = control.second->value();
93 modulation_data[
"source"] = connection->
source_name;
97 if (!line_mapping->
linear())
98 modulation_data[
"line_mapping"] = line_mapping->
stateToJson();
100 modulations.push_back(modulation_data);
103 settings_data[
"modulations"] = modulations;
109 wavetables.push_back(wavetable_creator->
stateToJson());
112 settings_data[
"wavetables"] = wavetables;
121 settings_data[
"lfos"] = lfos;
124 data[
"synth_version"] = ProjectInfo::versionString;
126 data[
"author"] = synth->
getAuthor().toStdString();
127 data[
"comments"] = synth->
getComments().toStdString();
128 data[
"preset_style"] = synth->
getStyle().toStdString();
130 std::string name = synth->
getMacroName(i).toStdString();
131 data[
"macro" + std::to_string(i + 1)] = name;
133 data[
"settings"] = settings_data;
139 for (
auto& control : controls) {
140 std::string name = control.first;
141 if (data.count(name)) {
143 control.second->set(value);
158 for (
const json& modulation : modulations) {
159 std::string source = modulation[
"source"];
160 std::string destination = modulation[
"destination"];
169 if (source.length() && destination.length()) {
175 if (modulation.count(
"line_mapping"))
193 for (
const json& wavetable : wavetables) {
196 wavetable_creator->
render();
203 for (
const json& lfo : lfos) {
212 if (data.count(
"preset_name")) {
213 std::string preset_name = data[
"preset_name"];
214 state[
"preset_name"] = preset_name;
217 if (data.count(
"author")) {
218 std::string author = data[
"author"];
219 state[
"author"] = author;
222 if (data.count(
"comments")) {
223 std::string comments = data[
"comments"];
224 state[
"comments"] = comments;
227 if (data.count(
"preset_style")) {
228 std::string style = data[
"preset_style"];
229 state[
"style"] = style;
233 std::string key =
"macro" + std::to_string(i + 1);
234 if (data.count(key)) {
235 std::string name = data[key];
239 state[key] =
"MACRO " + std::to_string(i + 1);
244 save_info[
"preset_name"] =
"";
245 save_info[
"author"] =
"";
246 save_info[
"comments"] =
"";
247 save_info[
"style"] =
"";
250 save_info[
"macro" + std::to_string(i + 1)] =
"MACRO " + std::to_string(i + 1);
254 json settings = state[
"settings"];
255 json modulations = settings[
"modulations"];
256 json sample = settings[
"sample"];
257 json wavetables = settings[
"wavetables"];
259 std::string version = state[
"synth_version"];
262 int sub_waveform = settings[
"sub_waveform"];
263 if (sub_waveform == 4)
265 else if (sub_waveform == 5)
267 settings[
"sub_waveform"] = sub_waveform;
269 int sub_octave = settings[
"sub_octave"];
272 int osc_1_filter_routing = settings[
"osc_1_filter_routing"];
273 int osc_2_filter_routing = settings[
"osc_2_filter_routing"];
274 int sample_filter_routing = settings[
"sample_filter_routing"];
275 int sub_filter_routing = settings[
"sub_filter_routing"];
276 settings[
"filter_1_osc1_input"] = 1 - osc_1_filter_routing;
277 settings[
"filter_1_osc2_input"] = 1 - osc_2_filter_routing;
278 settings[
"filter_1_sample_input"] = 1 - sample_filter_routing;
279 settings[
"filter_1_sub_input"] = 1 - sub_filter_routing;
280 settings[
"filter_2_osc1_input"] = osc_1_filter_routing;
281 settings[
"filter_2_osc2_input"] = osc_2_filter_routing;
282 settings[
"filter_2_sample_input"] = sample_filter_routing;
283 settings[
"filter_2_sub_input"] = sub_filter_routing;
285 int filter_1_style = settings[
"filter_1_style"];
286 if (filter_1_style == 2)
288 else if (filter_1_style == 3)
290 settings[
"filter_1_style"] = filter_1_style;
292 int filter_2_style = settings[
"filter_2_style"];
293 if (filter_2_style == 2)
295 else if (filter_2_style == 3)
297 settings[
"filter_2_style"] = filter_2_style;
301 std::string env_start =
"env_";
304 std::string number = std::to_string(i + 1);
305 std::string attack_string = env_start + number +
"_attack";
306 std::string decay_string = env_start + number +
"_decay";
307 std::string release_string = env_start + number +
"_release";
308 if (settings.count(attack_string) == 0)
311 settings[attack_string] = std::pow(settings[attack_string], 1.0f / 1.5f);
312 settings[decay_string] = std::pow(settings[decay_string], 1.0f / 1.5f);
313 settings[release_string] = std::pow(settings[release_string], 1.0f / 1.5f);
316 if (settings.count(
"wave_tables"))
317 settings[
"wavetables"] = settings[
"wave_tables"];
320 wavetables = settings[
"wavetables"];
323 int portamento_type = settings[
"portamento_type"];
324 settings[
"portamento_force"] = std::max(0, portamento_type - 1);
326 if (portamento_type == 0)
327 settings[
"portamento_time"] = -10.0f;
331 std::string env_start =
"env_";
334 std::string number = std::to_string(i + 1);
335 std::string attack_string = env_start + number +
"_attack";
336 std::string decay_string = env_start + number +
"_decay";
337 std::string release_string = env_start + number +
"_release";
338 if (settings.count(attack_string) == 0)
341 float adjust_power = 3.0f / 4.0f;
342 settings[attack_string] = std::pow(settings[attack_string], adjust_power);
343 settings[decay_string] = std::pow(settings[decay_string], adjust_power);
344 settings[release_string] = std::pow(settings[release_string], adjust_power);
349 std::string lfo_start =
"lfo_";
352 std::string number = std::to_string(i + 1);
353 std::string fade_string = lfo_start + number +
"_fade_time";
354 std::string delay_string = lfo_start + number +
"_delay_time";
355 settings[fade_string] = 0.0f;
356 settings[delay_string] = 0.0f;
361 static constexpr float adjustment = 0.70710678119f;
362 float osc_1_level = settings[
"osc_1_level"];
363 float osc_2_level = settings[
"osc_2_level"];
364 float sub_level = settings[
"sub_level"];
365 float sample_level = settings[
"sample_level"];
366 osc_1_level = adjustment * osc_1_level * osc_1_level;
367 osc_2_level = adjustment * osc_2_level * osc_2_level;
368 sub_level = adjustment * sub_level * sub_level;
369 sample_level = adjustment * sample_level * sample_level;
371 settings[
"osc_1_level"] = sqrtf(osc_1_level);
372 settings[
"osc_2_level"] = sqrtf(osc_2_level);
373 settings[
"sub_level"] = sqrtf(sub_level);
374 settings[
"sample_level"] = sqrtf(sample_level);
378 float reverb_damping = settings[
"reverb_damping"];
379 float reverb_feedback = settings[
"reverb_feedback"];
380 settings[
"decay_time"] = (reverb_feedback - 0.8f) * 10.0f;
381 settings[
"reverb_high_shelf_gain"] = -reverb_damping * 4.0f;
382 settings[
"reverb_pre_high_cutoff"] = 128.0f;
384 json new_modulations;
385 for (
json& modulation : modulations) {
386 if (modulation[
"destination"] ==
"reverb_damping")
387 modulation[
"destination"] =
"reverb_high_shelf_gain";
388 if (modulation[
"destination"] ==
"reverb_feedback")
389 modulation[
"destination"] =
"reverb_decay_time";
391 new_modulations.push_back(modulation);
393 modulations = new_modulations;
397 float sample_transpose = settings[
"sample_transpose"];
398 float sample_keytrack = settings[
"sample_keytrack"];
400 settings[
"sample_transpose"] = sample_transpose + 28.0f;
404 float osc_1_transpose = settings[
"osc_1_transpose"];
405 float osc_1_midi_track = settings[
"osc_1_midi_track"];
406 if (osc_1_midi_track == 0.0f)
407 settings[
"osc_1_transpose"] = osc_1_transpose - 48.0f;
409 float osc_2_transpose = settings[
"osc_2_transpose"];
410 float osc_2_midi_track = settings[
"osc_2_midi_track"];
411 if (osc_2_midi_track == 0.0f)
412 settings[
"osc_2_transpose"] = osc_2_transpose - 48.0f;
416 float float_order = settings[
"effect_chain_order"];
421 effect_order[i] += 1;
428 float osc_1_distortion_type = settings[
"osc_1_distortion_type"];
429 float osc_2_distortion_type = settings[
"osc_2_distortion_type"];
430 if (osc_1_distortion_type >= 10.0f)
431 settings[
"osc_1_distortion_type"] = osc_1_distortion_type + 1.0f;
432 if (osc_2_distortion_type >= 10.0f)
433 settings[
"osc_2_distortion_type"] = osc_2_distortion_type + 1.0f;
437 std::string lfo_start =
"lfo_";
440 std::string sync_type_string = lfo_start + std::to_string(i + 1) +
"_sync_type";
441 if (settings.count(sync_type_string)) {
442 float value = settings[sync_type_string];
444 settings[sync_type_string] = value - 1.0f;
456 json new_modulations;
457 for (
json& modulation : modulations) {
458 if (modulation[
"source"] ==
"perlin") {
460 modulation[
"source"] =
"random_1";
463 new_modulations.push_back(modulation);
467 modulations = new_modulations;
468 settings[
"random_1_sync"] = 0.0f;
469 settings[
"random_1_frequency"] = 1.65149612947f;
470 settings[
"random_1_stereo"] = 1.0f;
475 float osc_1_distortion_type = settings[
"osc_1_distortion_type"];
476 float osc_1_distortion_amount = settings[
"osc_1_distortion_amount"];
478 settings[
"osc_1_distortion_amount"] = 0.5f + 0.5f * osc_1_distortion_amount;
481 for (
json& modulation : modulations) {
482 if (modulation[
"destination"] ==
"osc_1_distortion_amount") {
483 std::string amount_string =
"modulation_" + std::to_string(index) +
"_amount";
484 float last_amount = settings[amount_string];
485 settings[amount_string] = 0.5f * last_amount;
492 float osc_2_distortion_type = settings[
"osc_2_distortion_type"];
493 float osc_2_distortion_amount = settings[
"osc_2_distortion_amount"];
495 settings[
"osc_2_distortion_amount"] = 0.5f + 0.5f * osc_2_distortion_amount;
498 for (
json& modulation : modulations) {
499 if (modulation[
"destination"] ==
"osc_2_distortion_amount") {
500 std::string amount_string =
"modulation_" + std::to_string(index) +
"_amount";
501 float last_amount = settings[amount_string];
502 settings[amount_string] = 0.5f * last_amount;
511 float osc_1_distortion_type = settings[
"osc_1_distortion_type"];
512 float osc_1_distortion_amount = settings[
"osc_1_distortion_amount"];
514 settings[
"osc_1_distortion_amount"] = 0.5f + 0.5f * osc_1_distortion_amount;
517 for (
json& modulation : modulations) {
518 if (modulation[
"destination"] ==
"osc_1_distortion_amount") {
519 std::string amount_string =
"modulation_" + std::to_string(index) +
"_amount";
520 float last_amount = settings[amount_string];
521 settings[amount_string] = 0.5f * last_amount;
528 float osc_2_distortion_type = settings[
"osc_2_distortion_type"];
529 float osc_2_distortion_amount = settings[
"osc_2_distortion_amount"];
531 settings[
"osc_2_distortion_amount"] = 0.5f + 0.5f * osc_2_distortion_amount;
534 for (
json& modulation : modulations) {
535 if (modulation[
"destination"] ==
"osc_2_distortion_amount") {
536 std::string amount_string =
"modulation_" + std::to_string(index) +
"_amount";
537 float last_amount = settings[amount_string];
538 settings[amount_string] = 0.5f * last_amount;
547 float compressor_low_band = settings[
"compressor_low_band"];
548 float compressor_high_band = settings[
"compressor_high_band"];
549 if (compressor_low_band && compressor_high_band)
550 settings[
"compressor_enabled_bands"] = 0;
551 else if (compressor_low_band)
552 settings[
"compressor_enabled_bands"] = 1;
553 else if (compressor_high_band)
554 settings[
"compressor_enabled_bands"] = 2;
556 settings[
"compressor_enabled_bands"] = 3;
560 static const int kRemapResolution = 32;
562 float osc_1_distortion_type = settings[
"osc_1_distortion_type"];
563 if (osc_1_distortion_type)
564 settings[
"osc_1_distortion_type"] = osc_1_distortion_type - 1.0f;
566 float osc_2_distortion_type = settings[
"osc_2_distortion_type"];
567 if (osc_2_distortion_type)
568 settings[
"osc_2_distortion_type"] = osc_2_distortion_type - 1.0f;
570 if (osc_1_distortion_type == 1.0f)
573 if (osc_2_distortion_type == 1.0f)
576 json new_modulations;
577 for (
json& modulation : modulations) {
578 if (osc_1_distortion_type == 1.0f && modulation[
"destination"] ==
"osc_1_distortion_amount")
579 modulation[
"destination"] =
"osc_1_spectral_morph_amount";
580 else if (osc_2_distortion_type == 1.0f && modulation[
"destination"] ==
"osc_2_distortion_amount")
581 modulation[
"destination"] =
"osc_2_spectral_morph_amount";
583 new_modulations.push_back(modulation);
586 osc_1_distortion_type = settings[
"osc_1_distortion_type"];
587 osc_2_distortion_type = settings[
"osc_2_distortion_type"];
588 if (osc_1_distortion_type == 7 || osc_1_distortion_type == 8 || osc_1_distortion_type == 9) {
589 float original_fm_amount = settings[
"osc_1_distortion_amount"];
590 float new_fm_amount = std::pow(original_fm_amount, 1.0f / 2.0f);
591 settings[
"osc_1_distortion_amount"] = new_fm_amount;
594 for (
json& modulation : new_modulations) {
595 if (modulation[
"destination"] ==
"osc_1_distortion_amount") {
596 std::string number = std::to_string(index);
597 std::string amount_string =
"modulation_" + number +
"_amount";
598 float last_amount = settings[amount_string];
599 if (last_amount == 0.0f)
602 bool bipolar = settings[
"modulation_" + number +
"_bipolar"] != 0.0f;
603 float min = std::min(original_fm_amount, original_fm_amount + last_amount);
604 float max = std::max(original_fm_amount, original_fm_amount + last_amount);
607 min = std::min(original_fm_amount + last_amount * 0.5f, original_fm_amount - last_amount * 0.5f);
608 max = std::max(original_fm_amount + last_amount * 0.5f, original_fm_amount - last_amount * 0.5f);
611 float min_target = std::pow(min, 1.0f / 2.0f);
612 float max_target = std::pow(max, 1.0f / 2.0f);
613 float new_amount = max_target - min_target;
615 new_amount = 2.0f * std::max(new_fm_amount - min_target, max_target - new_fm_amount);
616 settings[amount_string] = new_amount;
621 for (
int i = 0; i < kRemapResolution; ++i) {
622 float t = i / (kRemapResolution - 1.0f);
624 float adjusted_old_value = std::pow(old_value, 1.0f / 2.0f);
625 float y = 1.0f - (adjusted_old_value - min_target) / new_amount;
626 scale.
setPoint(i, std::pair<float, float>(t, y));
634 if (osc_2_distortion_type == 7 || osc_2_distortion_type == 8 || osc_2_distortion_type == 9) {
635 float original_fm_amount = settings[
"osc_2_distortion_amount"];
636 float new_fm_amount = std::pow(original_fm_amount, 1.0f / 2.0f);
637 settings[
"osc_2_distortion_amount"] = new_fm_amount;
640 for (
json& modulation : new_modulations) {
641 if (modulation[
"destination"] ==
"osc_2_distortion_amount") {
642 std::string number = std::to_string(index);
643 std::string amount_string =
"modulation_" + number +
"_amount";
644 float last_amount = settings[amount_string];
645 if (last_amount == 0.0f)
648 bool bipolar = settings[
"modulation_" + number +
"_bipolar"] != 0.0f;
649 float min = std::min(original_fm_amount, original_fm_amount + last_amount);
650 float max = std::max(original_fm_amount, original_fm_amount + last_amount);
653 min = std::min(original_fm_amount + last_amount * 0.5f, original_fm_amount - last_amount * 0.5f);
654 max = std::max(original_fm_amount + last_amount * 0.5f, original_fm_amount - last_amount * 0.5f);
657 float min_target = std::pow(min, 1.0f / 2.0f);
658 float max_target = std::pow(max, 1.0f / 2.0f);
659 float new_amount = max_target - min_target;
661 new_amount = 2.0f * std::max(new_fm_amount - min_target, max_target - new_fm_amount);
662 settings[amount_string] = new_amount;
667 for (
int i = 0; i < kRemapResolution; ++i) {
668 float t = i / (kRemapResolution - 1.0f);
670 float adjusted_old_value = std::pow(old_value, 1.0f / 2.0f);
671 float y = 1.0f - (adjusted_old_value - min_target) / new_amount;
672 scale.
setPoint(i, std::pair<float, float>(t, y));
680 modulations = new_modulations;
684 settings[
"osc_3_on"] = settings[
"sub_on"];
685 settings[
"osc_3_level"] = settings[
"sub_level"];
686 settings[
"osc_3_pan"] = settings[
"sub_pan"];
687 settings[
"osc_3_transpose"] = settings[
"sub_transpose"];
689 if (settings.count(
"sub_transpose_quantize"))
690 settings[
"osc_3_transpose_quantize"] = settings[
"sub_transpose_quantize"];
692 settings[
"osc_3_tune"] = settings[
"sub_tune"];
693 settings[
"osc_3_phase"] = 0.25f;
694 settings[
"osc_3_random_phase"] = 0.0f;
696 float sub_waveform = settings[
"sub_waveform"];
697 settings[
"osc_3_wave_frame"] = sub_waveform * 257.0f / 6.0f;
699 float sub_filter1 = settings[
"filter_1_sub_input"];
700 float sub_filter2 = settings[
"filter_2_sub_input"];
701 float sub_direct_out = settings[
"sub_direct_out"];
703 settings[
"osc_3_destination"] = 4.0f;
704 else if (sub_filter1 && sub_filter2)
705 settings[
"osc_3_destination"] = 2.0f;
706 else if (sub_filter2)
707 settings[
"osc_3_destination"] = 1.0f;
708 else if (sub_filter1)
709 settings[
"osc_3_destination"] = 0.0f;
711 settings[
"osc_3_destination"] = 3.0f;
713 float osc1_filter1 = settings[
"filter_1_osc1_input"];
714 float osc1_filter2 = settings[
"filter_2_osc1_input"];
715 if (osc1_filter1 && osc1_filter2)
716 settings[
"osc_1_destination"] = 2.0f;
717 else if (osc1_filter2)
718 settings[
"osc_1_destination"] = 1.0f;
719 else if (osc1_filter1)
720 settings[
"osc_1_destination"] = 0.0f;
722 settings[
"osc_1_destination"] = 3.0f;
724 float osc2_filter1 = settings[
"filter_1_osc2_input"];
725 float osc2_filter2 = settings[
"filter_2_osc2_input"];
726 if (osc2_filter1 && osc2_filter2)
727 settings[
"osc_2_destination"] = 2.0f;
728 else if (osc2_filter2)
729 settings[
"osc_2_destination"] = 1.0f;
730 else if (osc2_filter1)
731 settings[
"osc_2_destination"] = 0.0f;
733 settings[
"osc_2_destination"] = 3.0f;
735 float sample_filter1 = settings[
"filter_1_sample_input"];
736 float sample_filter2 = settings[
"filter_2_sample_input"];
737 if (sample_filter1 && sample_filter2)
738 settings[
"sample_destination"] = 2.0f;
739 else if (sample_filter2)
740 settings[
"sample_destination"] = 1.0f;
741 else if (sample_filter1)
742 settings[
"sample_destination"] = 0.0f;
744 settings[
"sample_destination"] = 3.0f;
749 wavetable_creator.
setName(
"Sub");
752 for (
int i = (
int)wavetables.size() - 1; i >= 0; --i)
753 new_wavetables.push_back(wavetables[i]);
755 new_wavetables.push_back(wavetable_creator.
stateToJson());
756 settings[
"wavetables"] = new_wavetables;
758 json new_modulations;
759 for (
json& modulation : modulations) {
760 if (modulation[
"destination"] ==
"sub_transpose")
761 modulation[
"destination"] =
"osc_3_transpose";
762 else if (modulation[
"destination"] ==
"sub_tune")
763 modulation[
"destination"] =
"osc_3_tune";
764 else if (modulation[
"destination"] ==
"sub_level")
765 modulation[
"destination"] =
"osc_3_level";
766 else if (modulation[
"destination"] ==
"sub_pan")
767 modulation[
"destination"] =
"osc_3_pan";
769 new_modulations.push_back(modulation);
772 modulations = new_modulations;
776 float flanger_tempo = settings[
"flanger_tempo"];
777 settings[
"flanger_tempo"] = flanger_tempo + 1.0f;
779 float phaser_tempo = settings[
"phaser_tempo"];
780 settings[
"phaser_tempo"] = phaser_tempo + 1.0f;
782 float chorus_tempo = settings[
"chorus_tempo"];
783 settings[
"chorus_tempo"] = chorus_tempo + 1.0f;
785 float delay_tempo = settings[
"delay_tempo"];
786 settings[
"delay_tempo"] = delay_tempo + 1.0f;
788 std::string lfo_start =
"lfo_";
790 std::string tempo_string = lfo_start + std::to_string(i + 1) +
"_tempo";
791 if (settings.count(tempo_string)) {
792 float tempo = settings[tempo_string];
793 settings[tempo_string] = tempo + 1.0f;
797 std::string random_start =
"random_";
799 std::string tempo_string = random_start + std::to_string(i + 1) +
"_tempo";
800 if (settings.count(tempo_string)) {
801 float tempo = settings[tempo_string];
802 settings[tempo_string] = tempo + 1.0f;
808 settings[
"delay_aux_sync"] = settings[
"delay_sync"];
809 settings[
"delay_aux_frequency"] = settings[
"delay_frequency"];
810 settings[
"delay_aux_tempo"] = settings[
"delay_tempo"];
812 float style = settings[
"delay_style"];
814 settings[
"delay_style"] = style + 1.0f;
818 settings[
"chorus_damping"] = 1.0f;
821 settings[
"stereo_mode"] = 1.0f;
822 float routing = settings[
"stereo_routing"];
825 settings[
"stereo_routing"] = 1.0f - routing;
827 settings[
"stereo_routing"] = routing;
831 float stereo_mode = settings[
"stereo_mode"];
832 float routing = settings[
"stereo_routing"];
833 if (stereo_mode == 0.0f)
834 settings[
"stereo_routing"] = 1.0f - routing;
838 float chorus_damping = settings[
"chorus_damping"];
839 settings[
"chorus_cutoff"] = 20.0f;
840 settings[
"chorus_spread"] = chorus_damping;
842 json new_modulations;
843 for (
json& modulation : modulations) {
844 if (modulation[
"destination"] ==
"chorus_damping")
845 modulation[
"destination"] =
"chorus_spread";
847 new_modulations.push_back(modulation);
849 modulations = new_modulations;
853 float osc_1_spectral_morph_type = 0.0f;
854 if (settings.count(
"osc_1_spectral_morph_type"))
855 osc_1_spectral_morph_type = settings[
"osc_1_spectral_morph_type"];
857 float osc_2_spectral_morph_type = 0.0f;
858 if (settings.count(
"osc_2_spectral_morph_type"))
859 osc_2_spectral_morph_type = settings[
"osc_2_spectral_morph_type"];
861 if (osc_1_spectral_morph_type == 9.0f) {
862 float osc_1_spectral_morph_amount = settings[
"osc_1_spectral_morph_amount"];
863 settings[
"osc_1_spectral_morph_amount"] = -0.5f * osc_1_spectral_morph_amount + 0.5f;
866 for (
json& modulation : modulations) {
867 if (modulation[
"destination"] ==
"osc_1_spectral_morph_amount") {
868 std::string name =
"modulation_" + std::to_string(index) +
"_amount";
869 float modulation_amount = settings[name];
870 settings[name] = modulation_amount * -0.5f;
876 if (osc_2_spectral_morph_type == 9.0f) {
877 float osc_2_spectral_morph_amount = settings[
"osc_2_spectral_morph_amount"];
878 settings[
"osc_2_spectral_morph_amount"] = -0.5f * osc_2_spectral_morph_amount + 0.5f;
881 for (
json& modulation : modulations) {
882 if (modulation[
"destination"] ==
"osc_2_spectral_morph_amount") {
883 std::string name =
"modulation_" + std::to_string(index) +
"_amount";
884 float modulation_amount = settings[name];
885 settings[name] = modulation_amount * -0.5f;
894 static constexpr float kFlangerCenterMultiply = 48.0f / 128.0f;
895 static constexpr float kFlangerCenterOffset = 53.69f;
896 static constexpr float kPhaserCenterMultiply = 48.0f / 128.0f;
898 if (settings.count(
"flanger_center")) {
899 float flanger_center = settings[
"flanger_center"];
900 settings[
"flanger_center"] = flanger_center + kFlangerCenterOffset;
904 for (
json& modulation : modulations) {
905 if (modulation[
"destination"] ==
"flanger_center") {
906 std::string name =
"modulation_" + std::to_string(index) +
"_amount";
907 float modulation_amount = settings[name];
908 settings[name] = modulation_amount * kFlangerCenterMultiply;
910 if (modulation[
"destination"] ==
"phaser_center") {
911 std::string name =
"modulation_" + std::to_string(index) +
"_amount";
912 float modulation_amount = settings[name];
913 settings[name] = modulation_amount * kPhaserCenterMultiply;
921 int filter_1_model = settings[
"filter_1_model"];
922 int filter_2_model = settings[
"filter_2_model"];
924 if (filter_1_model == 6) {
925 int filter_1_style = settings[
"filter_1_style"];
926 if (filter_1_style == 1)
927 settings[
"filter_1_style"] = 3;
930 if (filter_2_model == 6) {
931 int filter_2_style = settings[
"filter_2_style"];
932 if (filter_2_style == 1)
933 settings[
"filter_2_style"] = 3;
936 if (settings.count(
"filter_fx_model")) {
937 int filter_fx_model = settings[
"filter_fx_model"];
938 if (filter_fx_model == 6) {
939 int filter_fx_style = settings[
"filter_fx_style"];
940 if (filter_fx_style == 1)
941 settings[
"filter_fx_style"] = 3;
947 if (settings.count(
"osc_1_spectral_morph_type")) {
948 float osc_1_spectral_morph_type = settings[
"osc_1_spectral_morph_type"];
949 if (osc_1_spectral_morph_type == 10.0f)
950 settings[
"osc_1_spectral_morph_type"] = 7.0f;
953 if (settings.count(
"osc_2_spectral_morph_type")) {
954 float osc_2_spectral_morph_type = settings[
"osc_2_spectral_morph_type"];
955 if (osc_2_spectral_morph_type == 10.0f)
956 settings[
"osc_2_spectral_morph_type"] = 7.0f;
959 if (settings.count(
"osc_3_spectral_morph_type")) {
960 float osc_3_spectral_morph_type = settings[
"osc_3_spectral_morph_type"];
961 if (osc_3_spectral_morph_type == 10.0f)
962 settings[
"osc_3_spectral_morph_type"] = 7.0f;
968 std::string name =
"lfo_" + std::to_string(i) +
"_smooth_mode";
969 settings[name] = 0.0f;
974 float filter_1_model = settings[
"filter_1_model"];
975 if (filter_1_model == 4) {
976 settings[
"filter_1_blend"] = 0.0f;
977 settings[
"filter_1_style"] = 0.0f;
979 for (
json& modulation : modulations) {
980 if (modulation[
"destination"] ==
"filter_1_blend") {
981 std::string name =
"modulation_" + std::to_string(index) +
"_amount";
982 settings[name] = 0.0f;
989 float filter_2_model = settings[
"filter_2_model"];
990 if (filter_2_model == 4) {
991 settings[
"filter_2_blend"] = 0.0f;
992 settings[
"filter_2_style"] = 0.0f;
994 for (
json& modulation : modulations) {
995 if (modulation[
"destination"] ==
"filter_2_blend") {
996 std::string name =
"modulation_" + std::to_string(index) +
"_amount";
997 settings[name] = 0.0f;
1005 settings[
"modulations"] = modulations;
1006 settings[
"sample"] = sample;
1007 state[
"settings"] = settings;
1012 std::string version = data[
"synth_version"];
1015 if (compare_feature_versions > 0)
1019 if (compare_versions < 0 || data[
"settings"].count(
"sub_octave"))
1022 json settings = data[
"settings"];
1023 json modulations = settings[
"modulations"];
1024 json sample = settings[
"sample"];
1025 json wavetables = settings[
"wavetables"];
1026 json lfos = settings[
"lfos"];
1040 static constexpr int kMaxCharacters = 40;
1041 static constexpr int kMinSize = 60;
1042 FileInputStream file_stream(file);
1044 if (file_stream.getTotalLength() < kMinSize)
1047 file_stream.readByte();
1048 file_stream.readByte();
1049 MemoryBlock author_memory_block;
1050 file_stream.readIntoMemoryBlock(author_memory_block, 6);
1052 char end_quote = file_stream.readByte();
1053 char colon = file_stream.readByte();
1054 char begin_quote = file_stream.readByte();
1055 if (author_memory_block.toString() !=
"author" || end_quote !=
'"' || colon !=
':' || begin_quote !=
'"') {
1057 json parsed_json_state = json::parse(file.loadFileAsString().toStdString(),
nullptr,
false);
1060 catch (
const json::exception& e) {
1065 MemoryBlock name_memory_block;
1066 file_stream.readIntoMemoryBlock(name_memory_block, kMaxCharacters);
1067 String name = name_memory_block.toString();
1069 if (!name.contains(
"\""))
1070 return name.toStdString();
1073 tokens.addTokens(name,
"\"",
"");
1079 static constexpr int kMinSize = 5000;
1080 FileInputStream file_stream(file);
1082 if (file_stream.getTotalLength() < kMinSize)
1085 MemoryBlock style_memory_block;
1086 file_stream.readIntoMemoryBlock(style_memory_block, kMinSize);
1089 tokens.addTokens(style_memory_block.toString(),
"\"",
"");
1090 bool found_style =
false;
1091 for (String token : tokens) {
1092 if (found_style && token.trim() !=
":")
1094 if (token ==
"preset_style")
1102 if (data.count(
"author"))
1103 return data[
"author"];
1108 if (data.count(
"license"))
1109 return data[
"license"];
1114#if defined(JUCE_DATA_STRUCTURES_H_INCLUDED)
1115 PropertiesFile::Options config_options;
1116 config_options.applicationName =
"Vial";
1117 config_options.osxLibrarySubFolder =
"Application Support";
1118 config_options.filenameSuffix =
"config";
1121 config_options.folderName =
"." + String(ProjectInfo::projectName).toLowerCase();
1123 config_options.folderName = String(ProjectInfo::projectName).toLowerCase();
1126 return config_options.getDefaultFile();
1134 if (!data_dir.exists() || !data_dir.isDirectory())
1136 File file = data_dir.getChildFile(
"crash.txt");
1137 file.replaceWithText(crash_log);
1142 if (!data_dir.exists() || !data_dir.isDirectory())
1146 file.appendText(error_log +
"\n");
1150#if defined(JUCE_DATA_STRUCTURES_H_INCLUDED)
1151 PropertiesFile::Options config_options;
1152 config_options.applicationName =
"Vial";
1153 config_options.osxLibrarySubFolder =
"Application Support";
1154 config_options.filenameSuffix =
"favorites";
1157 config_options.folderName =
"." + String(ProjectInfo::projectName).toLowerCase();
1159 config_options.folderName = String(ProjectInfo::projectName).toLowerCase();
1162 return config_options.getDefaultFile();
1169#if defined(JUCE_DATA_STRUCTURES_H_INCLUDED)
1170 PropertiesFile::Options config_options;
1171 config_options.applicationName =
"Vial";
1172 config_options.osxLibrarySubFolder =
"Application Support";
1173 config_options.filenameSuffix =
"skin";
1176 config_options.folderName =
"." + String(ProjectInfo::projectName).toLowerCase();
1178 config_options.folderName = String(ProjectInfo::projectName).toLowerCase();
1181 return config_options.getDefaultFile();
1189 if (!config_file.exists())
1193 json parsed = json::parse(config_file.loadFileAsString().toStdString(),
nullptr,
false);
1194 if (parsed.is_discarded())
1198 catch (
const json::exception& e) {
1205 if (!favorites_file.exists())
1209 json parsed = json::parse(favorites_file.loadFileAsString().toStdString(),
nullptr,
false);
1210 if (parsed.is_discarded())
1214 catch (
const json::exception& e) {
1221 favorites[new_favorite.getFullPathName().toStdString()] = 1;
1227 std::string path = old_favorite.getFullPathName().toStdString();
1229 if (favorites.count(path)) {
1230 favorites.erase(path);
1238 std::set<std::string> favorites;
1239 for (
auto& pair : favorites_json.items())
1240 favorites.insert(pair.key());
1248 if (!config_file.exists())
1249 config_file.create();
1250 config_file.replaceWithText(config_state.dump());
1256 if (!favorites_file.exists())
1257 favorites_file.create();
1258 favorites_file.replaceWithText(favorites_json.dump());
1264 data[
"author"] = author;
1270 data[
"ttwt_language"] = language;
1277 data[
"synth_version"] = ProjectInfo::versionString;
1284 data[
"content_version"] = version;
1290 data[
"check_for_updates"] = check_for_updates;
1296 data[
"work_offline"] = work_offline;
1302 data[
"loaded_skin"] = name;
1308 data[
"animate_widgets"] = animate_widgets;
1314 data[
"hz_frequency"] = hz_frequency;
1326 data[
"window_size"] = window_size;
1331 std::wstring chromatic_layout;
1343 down_key = octave_controls.first;
1344 up_key = octave_controls.second;
1349 layout_data[
"chromatic_layout"] = chromatic_layout;
1350 layout_data[
"octave_up"] = up_key;
1351 layout_data[
"octave_down"] = down_key;
1354 data[
"keyboard_layout"] = layout_data;
1361 json midi_mapping_data;
1363 for (
auto& midi_mapping : midi_learn_map) {
1365 midi_map_data[
"source"] = midi_mapping.first;
1367 json destinations_data;
1368 for (
auto& midi_destination : midi_mapping.second) {
1369 json destination_data;
1371 destination_data[
"destination"] = midi_destination.first;
1372 destination_data[
"min_range"] = midi_destination.second->min;
1373 destination_data[
"max_range"] = midi_destination.second->max;
1374 destinations_data.push_back(destination_data);
1377 midi_map_data[
"destinations"] = destinations_data;
1378 midi_mapping_data.push_back(midi_map_data);
1382 data[
"midi_learn"] = midi_mapping_data;
1394 layout->
setUpKey(octave_controls.second);
1398 if (data.count(
"midi_learn")) {
1401 json midi_mapping_data = data[
"midi_learn"];
1402 for (
json& midi_map_data : midi_mapping_data) {
1403 int source = midi_map_data[
"source"];
1405 if (midi_map_data.count(
"destinations")) {
1406 json destinations_data = midi_map_data[
"destinations"];
1407 for (
json& midi_destination : destinations_data) {
1408 std::string dest = midi_destination[
"destination"];
1419 if (data.count(
"data_directory")) {
1420 std::string path = data[
"data_directory"];
1421 File directory(path);
1422 File packages = directory.getChildFile(kInstalledPacksFile);
1423 return directory.exists() && directory.isDirectory() && packages.exists();
1430 if (data.count(
"data_directory") == 0)
1433 std::string path = data[
"data_directory"];
1434 File directory(path);
1435 if (!directory.exists() || !directory.isDirectory())
1438 return directory.getChildFile(kAvailablePacksFile);
1443 if (!packs_file.exists())
1447 json parsed = json::parse(packs_file.loadFileAsString().toStdString(),
nullptr,
false);
1448 if (parsed.is_discarded())
1452 catch (
const json::exception& e) {
1459 if (data.count(
"data_directory") == 0)
1462 std::string path = data[
"data_directory"];
1463 File directory(path);
1464 if (!directory.exists() || !directory.isDirectory())
1467 return directory.getChildFile(kInstalledPacksFile);
1472 if (!packs_file.exists())
1476 json parsed = json::parse(packs_file.loadFileAsString().toStdString(),
nullptr,
false);
1477 if (parsed.is_discarded())
1481 catch (
const json::exception& e) {
1489 if (!packs_file.exists())
1490 packs_file.create();
1491 packs_file.replaceWithText(packs.dump());
1496 packs[std::to_string(
id)] = 1;
1502 std::string cleaned = String(name).removeCharacters(
" ._").toLowerCase().toStdString();
1510 std::string path = data_directory.getFullPathName().toStdString();
1511 data[
"data_directory"] = path;
1522 if (!data.count(
"synth_version"))
1525 std::string version = data[
"synth_version"];
1543 Time current_time = Time::getCurrentTime();
1544 Time build_time = getBuildTime();
1546 RelativeTime time_since_compile = current_time - build_time;
1547 int days_since_compile = time_since_compile.inDays();
1548 return EXPIRE_DAYS - days_since_compile;
1557 if (!data.count(
"check_for_updates"))
1560 return data[
"check_for_updates"];
1566 if (!data.count(
"work_offline"))
1569 return data[
"work_offline"];
1575 if (!data.count(
"loaded_skin"))
1578 return data[
"loaded_skin"];
1584 if (!data.count(
"animate_widgets"))
1587 return data[
"animate_widgets"];
1593 if (!data.count(
"hz_frequency"))
1596 return data[
"hz_frequency"];
1602 if (!data.count(
"authenticated"))
1605 return data[
"authenticated"];
1611 if (!data.count(
"oversampling_amount"))
1614 return data[
"oversampling_amount"];
1618 static constexpr float kMinWindowSize = 0.25f;
1622 if (!data.count(
"window_size"))
1625 return std::max<float>(kMinWindowSize, data[
"window_size"]);
1631 if (!data.count(
"synth_version"))
1634 std::string version = data[
"synth_version"];
1641 if (!data.count(
"content_version"))
1644 std::string version = data[
"content_version"];
1651 if (data.count(
"keyboard_layout")) {
1652 json layout = data[
"keyboard_layout"];
1654 if (layout.count(
"chromatic_layout"))
1655 return layout[
"chromatic_layout"];
1664 if (!data.count(
"ttwt_language"))
1667 std::string language = data[
"ttwt_language"];
1674 if (data.count(
"author"))
1675 return data[
"author"];
1684 if (data.count(
"keyboard_layout")) {
1685 json layout = data[
"keyboard_layout"];
1686 std::wstring down = layout[
"octave_down"];
1687 std::wstring up = layout[
"octave_up"];
1688 octave_controls.first = down[0];
1689 octave_controls.second = up[0];
1692 return octave_controls;
1697 json wavetable_folders;
1698 for (std::string& folder : folders)
1699 wavetable_folders.push_back(folder);
1700 data[name] = wavetable_folders;
1707 std::vector<std::string> folders;
1709 if (data.count(name)) {
1710 json folder_list = data[name];
1711 for (
json& folder : folder_list)
1712 folders.push_back(folder);
1720 if (data.count(
"data_directory")) {
1721 std::string path = data[
"data_directory"];
1723 if (folder.exists() && folder.isDirectory())
1728 File directory = File(kLinuxUserDataDirectory);
1729 String xdg_data_home = SystemStats::getEnvironmentVariable (
"XDG_DATA_HOME", {});
1731 if (!xdg_data_home.trim().isEmpty())
1732 directory = File(xdg_data_home).getChildFile(
"vial");
1734#elif defined(__APPLE__)
1735 File home_directory = File::getSpecialLocation(File::userHomeDirectory);
1736 File directory = home_directory.getChildFile(
"Music").getChildFile(
"Vial");
1738 File documents_dir = File::getSpecialLocation(File::userDocumentsDirectory);
1739 File directory = documents_dir.getChildFile(
"Vial");
1747 std::vector<File> directories;
1749 if (!data_dir.exists() || !data_dir.isDirectory())
1752 Array<File> sub_folders;
1753 sub_folders.add(data_dir);
1754 data_dir.findChildFiles(sub_folders, File::findDirectories,
false);
1755 for (
const File& sub_folder : sub_folders) {
1756 File directory = sub_folder.getChildFile(folder_name);
1757 if (directory.exists() && directory.isDirectory())
1758 directories.push_back(directory);
1786 if (!directory.exists())
1787 directory.createDirectory();
1793 if (!directory.exists())
1794 directory.createDirectory();
1800 if (!directory.exists())
1801 directory.createDirectory();
1807 if (!directory.exists())
1808 directory.createDirectory();
1814 if (!directory.exists())
1815 directory.createDirectory();
1821 if (!directory.exists())
1822 directory.createDirectory();
1827 const std::vector<File>& directories) {
1829 for (
const File& directory : directories) {
1830 if (directory.exists() && directory.isDirectory())
1831 directory.findChildFiles(files, File::findFiles,
true, extensions);
1856 std::vector<File> directories = {
1864 std::vector<File> directories = {
1872 std::vector<File> directories = {
1880 std::vector<File> directories = {
1892 b.upToLastOccurrenceOf(
".",
false,
true));
1899 if (a.isEmpty() && b.isEmpty())
1902 String major_version_a = a.upToFirstOccurrenceOf(
".",
false,
true);
1903 String major_version_b = b.upToFirstOccurrenceOf(
".",
false,
true);
1905 if (!major_version_a.containsOnly(
"0123456789"))
1906 major_version_a =
"0";
1907 if (!major_version_b.containsOnly(
"0123456789"))
1908 major_version_b =
"0";
1910 int major_value_a = major_version_a.getIntValue();
1911 int major_value_b = major_version_b.getIntValue();
1913 if (major_value_a > major_value_b)
1915 else if (major_value_a < major_value_b)
1918 b.fromFirstOccurrenceOf(
".",
false,
true));
1922 const std::string& additional_folders_name,
const File& current_file,
int shift) {
1927 for (
const std::string& path : additional)
1928 directories.push_back(File(path));
1930 Array<File> all_files;
1932 if (all_files.isEmpty())
1935 all_files.sort(file_sorter);
1936 int index = all_files.indexOf(current_file);
1938 return all_files[0];
1939 return all_files[(index + shift + all_files.size()) % all_files.size()];
A class for generating and storing a line shape, defined by a series of points and associated powers.
Definition line_generator.h:20
void render()
Renders the line into the internal buffer based on the current points and settings.
Definition line_generator.cpp:149
force_inline void setPoint(int index, std::pair< float, float > point)
Sets the position of a specific point.
Definition line_generator.h:337
force_inline bool linear() const
Indicates whether the line is currently a simple linear shape.
Definition line_generator.h:273
void jsonToState(json data)
Restores the line state from a given JSON object.
Definition line_generator.cpp:125
force_inline void setNumPoints(int num_points)
Sets the number of points currently in use.
Definition line_generator.h:360
json stateToJson()
Converts the current state of the line into a JSON object.
Definition line_generator.cpp:96
void initLinear()
Initializes the line to a simple linear shape (from 1.0 at x=0 to 0.0 at x=1).
Definition line_generator.cpp:11
A helper class for sorting files in ascending order based on their names.
Definition load_save.h:34
static void saveWindowSize(float window_size)
Saves the window size scaling factor.
Definition load_save.cpp:1324
static const std::string kPresetFolderName
Definition load_save.h:74
static void saveJsonToConfig(json config_state)
Saves a given JSON object to the configuration file.
Definition load_save.cpp:1245
static std::vector< File > getSkinDirectories()
Gets directories that should contain skins.
Definition load_save.cpp:1772
static std::string getLoadedSkin()
Retrieves the currently loaded skin name.
Definition load_save.cpp:1572
static void getAllUserLfos(Array< File > &lfos)
Retrieves all user LFO shapes (from data and user directories).
Definition load_save.cpp:1871
static void getAllWavetables(Array< File > &wavetables)
Retrieves all wavetables from wavetable directories.
Definition load_save.cpp:1839
static const std::string kSkinFolderName
Definition load_save.h:76
static String getStyleFromFile(const File &file)
Extracts the style from a given preset file.
Definition load_save.cpp:1078
static File getAvailablePacksFile()
Retrieves the file listing available packs.
Definition load_save.cpp:1428
static void getAllSamples(Array< File > &samples)
Retrieves all samples (wav files) from sample directories.
Definition load_save.cpp:1851
static void saveAuthor(std::string author)
Saves the provided author name to the config.
Definition load_save.cpp:1261
static std::vector< File > getPresetDirectories()
Gets directories that should contain presets.
Definition load_save.cpp:1764
static float loadWindowSize()
Loads the saved window size scaling factor.
Definition load_save.cpp:1617
static void saveAdditionalFolders(const std::string &name, std::vector< std::string > folders)
Saves additional folder paths for presets, wavetables, or samples.
Definition load_save.cpp:1695
static const std::string kSampleFolderName
Definition load_save.h:77
static void markPackInstalled(int id)
Marks a pack as installed by ID in the packs file.
Definition load_save.cpp:1494
static bool shouldAnimateWidgets()
Determines if widget animations are enabled.
Definition load_save.cpp:1581
static String loadContentVersion()
Loads the saved content version string.
Definition load_save.cpp:1638
static std::pair< wchar_t, wchar_t > getComputerKeyboardOctaveControls()
Retrieves the keys used for octave shifts on the computer keyboard layout.
Definition load_save.cpp:1680
static const std::string kAdditionalWavetableFoldersName
Definition load_save.h:79
static File getUserDirectory()
Retrieves the user directory inside the data directory.
Definition load_save.cpp:1784
static bool shouldWorkOffline()
Checks if Vital should operate in offline mode.
Definition load_save.cpp:1563
static void writeCrashLog(String crash_log)
Writes a crash log to a file in the data directory.
Definition load_save.cpp:1132
static File getUserPresetDirectory()
Retrieves the user's preset directory.
Definition load_save.cpp:1791
static bool isInstalled()
Checks if Vital is fully installed (data directory present).
Definition load_save.cpp:1515
static File getDataDirectory()
Gets the current data directory from the config.
Definition load_save.cpp:1718
static void getAllFilesOfTypeInDirectories(Array< File > &files, const String &extensions, const std::vector< File > &directories)
Scans a set of directories for files matching certain extensions.
Definition load_save.cpp:1826
static void getAllUserPresets(Array< File > &presets)
Retrieves all user presets (from data and user directories).
Definition load_save.cpp:1855
static void saveContentVersion(std::string version)
Saves the current content version to the config file.
Definition load_save.cpp:1281
static void saveInstalledPacks(const json &packs)
Saves the given JSON pack configuration to the installed packs file.
Definition load_save.cpp:1486
static std::vector< File > getLfoDirectories()
Gets directories that should contain LFO shapes.
Definition load_save.cpp:1780
static String loadVersion()
Loads the saved synth version string.
Definition load_save.cpp:1628
static std::vector< std::string > getAdditionalFolders(const std::string &name)
Retrieves a list of additional folder paths for a given category.
Definition load_save.cpp:1705
static void saveMidiMapConfig(MidiManager *midi_manager)
Saves MIDI mapping configuration.
Definition load_save.cpp:1358
static void loadControls(SynthBase *synth, const json &data)
Loads controls from the given JSON data into a SynthBase instance.
Definition load_save.cpp:137
static void convertPcmToFloatBuffer(json &data, const std::string &field)
Converts a PCM buffer field in JSON to a float buffer in base64.
Definition load_save.cpp:61
static void saveUpdateCheckConfig(bool check_for_updates)
Saves the user's preference regarding update checks.
Definition load_save.cpp:1288
static bool doesExpire()
Checks if this build of Vital includes an expiration mechanism.
Definition load_save.cpp:1533
static void saveJsonToFavorites(json favorites_json)
Saves a JSON object of favorites to the favorites file.
Definition load_save.cpp:1253
static void saveVersionConfig()
Saves the current synth version to the config file.
Definition load_save.cpp:1274
static void loadLfos(SynthBase *synth, const json &lfos)
Loads LFO states (line shapes) from a JSON array into a SynthBase.
Definition load_save.cpp:201
static bool displayHzFrequency()
Determines if frequencies should be displayed in Hz.
Definition load_save.cpp:1590
static void saveLayoutConfig(vital::StringLayout *layout)
Saves layout configuration (keyboard layout and octave controls).
Definition load_save.cpp:1330
static File getUserWavetableDirectory()
Retrieves the user's wavetable directory.
Definition load_save.cpp:1798
static void addFavorite(const File &new_favorite)
Adds a new favorite preset or item to the favorites file.
Definition load_save.cpp:1219
static void saveAnimateWidgets(bool animate_widgets)
Saves the widget animation preference.
Definition load_save.cpp:1306
static void getAllPresets(Array< File > &presets)
Retrieves all preset files from preset directories.
Definition load_save.cpp:1835
static void savePreferredTTWTLanguage(std::string language)
Saves a preferred Text-To-Wavetable (TTWT) language to the config.
Definition load_save.cpp:1268
static File getInstalledPacksFile()
Retrieves the file that stores information about installed packs.
Definition load_save.cpp:1457
static void initSaveInfo(std::map< std::string, String > &save_info)
Initializes save_info with default values for preset information.
Definition load_save.cpp:243
static void getAllSkins(Array< File > &skins)
Retrieves all skins from skin directories.
Definition load_save.cpp:1843
static File getUserSkinDirectory()
Retrieves the user's skin directory.
Definition load_save.cpp:1805
static File getShiftedFile(const String directory_name, const String &extensions, const std::string &additional_folders_name, const File ¤t_file, int shift)
Given a directory name and extensions, returns a file shifted by some offset from the current file.
Definition load_save.cpp:1921
static int getOversamplingAmount()
Retrieves the current oversampling amount.
Definition load_save.cpp:1608
static json stateToJson(SynthBase *synth, const CriticalSection &critical_section)
Converts the state of a given SynthBase to JSON.
Definition load_save.cpp:78
static std::string getLicense(json state)
Extracts the license information from a JSON state, if present.
Definition load_save.cpp:1107
static std::string getPreferredTTWTLanguage()
Returns the preferred Text-To-Wavetable language, if set.
Definition load_save.cpp:1661
static void loadModulations(SynthBase *synth, const json &modulations)
Loads modulation connections from JSON data into a SynthBase instance.
Definition load_save.cpp:154
static bool jsonToState(SynthBase *synth, std::map< std::string, String > &save_info, json state)
Loads a JSON state into the given SynthBase, applying older version updates if necessary.
Definition load_save.cpp:1011
static json getInstalledPacks()
Returns a JSON list of installed packs.
Definition load_save.cpp:1470
static json getFavoritesJson()
Parses and returns the favorites JSON data.
Definition load_save.cpp:1203
static void removeFavorite(const File &old_favorite)
Removes a favorite item from the favorites.
Definition load_save.cpp:1225
static json updateFromOldVersion(json state)
Updates a JSON state from an older version of Vital's format to the current version.
Definition load_save.cpp:253
static json getAvailablePacks()
Parses and returns JSON data about available packs.
Definition load_save.cpp:1441
static void saveAuthenticated(bool authenticated)
Saves the user's authentication status.
Definition load_save.cpp:1318
static File getConfigFile()
Retrieves the main configuration file path for Vital.
Definition load_save.cpp:1113
static const std::string kLfoFolderName
Definition load_save.h:78
static bool authenticated()
Checks if the user is authenticated.
Definition load_save.cpp:1599
static void saveDataDirectory(const File &data_directory)
Saves the given directory as the data directory in the configuration.
Definition load_save.cpp:1508
static std::vector< File > getDirectories(const String &folder_name)
Retrieves directories of a given folder name under the data directory structure.
Definition load_save.cpp:1745
static bool isExpired()
Checks if this build of Vital has expired.
Definition load_save.cpp:1529
static void getAllUserWavetables(Array< File > &wavetables)
Retrieves all user wavetables (from data and user directories).
Definition load_save.cpp:1863
static bool shouldCheckForUpdates()
Checks if Vital should perform update checks.
Definition load_save.cpp:1554
static int compareVersionStrings(String a, String b)
Compares two version strings.
Definition load_save.cpp:1895
static void loadConfig(MidiManager *midi_manager, vital::StringLayout *layout=nullptr)
Loads configuration data into a MidiManager and optional StringLayout.
Definition load_save.cpp:1386
static std::string getAuthor()
Retrieves the saved author name from the config.
Definition load_save.cpp:1671
static int getDaysToExpire()
Returns the number of days remaining until expiration.
Definition load_save.cpp:1541
static void convertBufferToPcm(json &data, const std::string &field)
Converts a float buffer field in JSON to PCM format in base64.
Definition load_save.cpp:44
static std::vector< File > getWavetableDirectories()
Gets directories that should contain wavetables.
Definition load_save.cpp:1768
static void loadSaveState(std::map< std::string, String > &save_info, json data)
Extracts and stores basic preset info (name, author, comments, style, macros) from JSON data.
Definition load_save.cpp:211
static void saveDisplayHzFrequency(bool display_hz)
Saves the preference to display frequency in Hz.
Definition load_save.cpp:1312
static std::vector< File > getSampleDirectories()
Gets directories that should contain samples.
Definition load_save.cpp:1776
static File getDefaultSkin()
Retrieves the file specifying the default skin.
Definition load_save.cpp:1168
static const std::string kAdditionalSampleFoldersName
Definition load_save.h:80
static void writeErrorLog(String error_log)
Appends an error message to an error log file.
Definition load_save.cpp:1140
static void getAllLfos(Array< File > &lfos)
Retrieves all LFO shapes from LFO directories.
Definition load_save.cpp:1847
static String getAuthorFromFile(const File &file)
Extracts the author's name from a given preset file.
Definition load_save.cpp:1039
static const std::string kWavetableFolderName
Definition load_save.h:75
static bool hasDataDirectory()
Checks if a data directory is properly configured (exists and has packs.json).
Definition load_save.cpp:1417
static File getUserSampleDirectory()
Retrieves the user's sample directory.
Definition load_save.cpp:1812
static std::wstring getComputerKeyboardLayout()
Retrieves the saved computer keyboard layout for playing notes.
Definition load_save.cpp:1648
static int compareFeatureVersionStrings(String a, String b)
Compares two feature version strings (ignoring patch-level differences).
Definition load_save.cpp:1887
static File getUserLfoDirectory()
Retrieves the user's LFO directory.
Definition load_save.cpp:1819
static void loadWavetables(SynthBase *synth, const json &wavetables)
Loads wavetable configurations into a SynthBase from a JSON array.
Definition load_save.cpp:188
static json getConfigJson()
Parses and returns the main configuration JSON.
Definition load_save.cpp:1187
static File getFavoritesFile()
Retrieves the file storing the user's favorites.
Definition load_save.cpp:1149
static void saveLoadedSkin(const std::string &name)
Saves the currently loaded skin name to the config.
Definition load_save.cpp:1300
static const std::string kUserDirectoryName
Various folder and directory name constants.
Definition load_save.h:73
static bool wasUpgraded()
Checks if Vital was upgraded from a previous version.
Definition load_save.cpp:1519
static void getAllUserSamples(Array< File > &samples)
Retrieves all user samples (from data and user directories).
Definition load_save.cpp:1879
static void saveWorkOffline(bool work_offline)
Saves the user's preference for working offline.
Definition load_save.cpp:1294
static void loadSample(SynthBase *synth, const json &sample)
Loads a sample configuration into the SynthBase from a JSON object.
Definition load_save.cpp:182
static std::set< std::string > getFavorites()
Retrieves all favorites as a set of string paths.
Definition load_save.cpp:1235
The MidiManager class handles all incoming MIDI messages and directs them to the synthesizer engine.
Definition midi_manager.h:44
midi_map getMidiLearnMap()
Returns the current MIDI learn map.
Definition midi_manager.h:317
void setMidiLearnMap(const midi_map &midi_learn_map)
Sets the current MIDI learn map, overriding existing mappings.
Definition midi_manager.h:324
std::map< int, std::map< std::string, const vital::ValueDetails * > > midi_map
A nested type defining a map from MIDI controls to a map of parameter names and their ValueDetails.
Definition midi_manager.h:52
A base class providing foundational functionality for the Vital synthesizer’s engine,...
Definition synth_base.h:42
bool connectModulation(const std::string &source, const std::string &destination)
Connects a modulation source to a destination parameter.
Definition synth_base.cpp:165
String getMacroName(int index)
Gets the name of a macro control by index.
Definition synth_base.cpp:717
vital::ModulationConnectionBank & getModulationBank()
Retrieves the ModulationConnectionBank managing all modulation connections.
Definition synth_base.cpp:730
String getAuthor()
Gets the author of the current preset.
Definition synth_base.cpp:701
void checkOversampling()
Checks and updates oversampling settings. May be called if parameters affecting oversampling change.
Definition synth_base.cpp:741
String getComments()
Gets the comments for the current preset.
Definition synth_base.cpp:705
LineGenerator * getLfoSource(int index)
Retrieves an LFO source by index.
Definition synth_base.cpp:278
void modWheelGuiChanged(vital::mono_float value)
Called when the mod wheel changes via the GUI or another external source.
Definition synth_base.cpp:80
String getPresetName()
Gets the current preset’s name.
Definition synth_base.cpp:713
WavetableCreator * getWavetableCreator(int index)
Gets a WavetableCreator for a given oscillator index.
Definition synth_base.cpp:270
vital::Sample * getSample()
Gets the Sample object used by the engine.
Definition synth_base.cpp:274
vital::control_map & getControls()
Provides access to the controls map (parameter name to Parameter pointer).
Definition synth_base.h:477
void clearModulations()
Clears all modulation connections.
Definition synth_base.cpp:196
vital::SoundEngine * getEngine()
Returns a pointer to the SoundEngine used for audio and modulation processing.
Definition synth_base.h:484
String getStyle()
Gets the style of the current preset.
Definition synth_base.cpp:709
A class responsible for creating complete wavetables from groups of wavetable components.
Definition wavetable_creator.h:27
void initPredefinedWaves()
Definition wavetable_creator.cpp:171
json stateToJson()
Definition wavetable_creator.cpp:477
void jsonToState(json data)
Definition wavetable_creator.cpp:493
void setName(const std::string &name)
Sets the name of the wavetable.
Definition wavetable_creator.h:90
float render(int position)
Definition wavetable_creator.cpp:59
A container managing a fixed number of ModulationConnections.
Definition synth_types.h:87
ModulationConnection * atIndex(int index)
Retrieves a ModulationConnection by index.
Definition synth_types.h:114
static const ValueDetails & getDetails(const std::string &name)
Definition synth_parameters.h:200
Holds and manages a single sampled waveform, including stereo or mono data and multiple band-limited ...
Definition sample_source.h:25
void jsonToState(json data)
Restores the sample's state from a JSON object (including audio data).
Definition sample_source.cpp:351
json stateToJson()
Exports the sample state (metadata and sample data) to a JSON object.
Definition sample_source.cpp:333
Manages a keyboard layout mapping for a computer keyboard used as a MIDI input device.
Definition synth_types.h:134
void setDownKey(wchar_t down_key)
Sets the character assigned to decrease the octave.
Definition synth_types.h:181
void setUpKey(wchar_t up_key)
Sets the character assigned to increase the octave.
Definition synth_types.h:167
wchar_t getUpKey()
Gets the character assigned to increase the octave.
Definition synth_types.h:160
std::wstring getLayout()
Retrieves the current keyboard layout (a wstring of character-to-note mappings).
Definition synth_types.h:146
void setLayout(const std::wstring &layout)
Sets the current keyboard layout.
Definition synth_types.h:153
wchar_t getDownKey()
Gets the character assigned to decrease the octave.
Definition synth_types.h:174
Processor * getMonoModulationDestination(std::string name)
Retrieves a mono modulation destination by name.
Definition synth_module.cpp:382
Output * getModulationSource(std::string name)
Retrieves a modulation source output by name.
Definition synth_module.cpp:350
@ kFormant
Formant shifting.
Definition synth_oscillator.h:148
@ kSync
Sync distortion.
Definition synth_oscillator.h:147
@ kLowPass
Lowpass morph.
Definition synth_oscillator.h:134
A class representing a wavetable, holding multiple frames of waveforms and their frequency-domain rep...
Definition wavetable.h:20
nlohmann::json json
Definition line_generator.h:7
#define STRINGIFY(x)
Definition load_save.cpp:11
@ kNumEffects
Definition synth_constants.h:187
@ kFilterFx
Definition synth_constants.h:183
void floatToPcmData(int16_t *pcm_data, const float *float_data, int size)
Converts floating-point audio data to 16-bit PCM data.
Definition utils.cpp:77
void decodeFloatToOrder(int *order, mono_float float_code, int size)
Decodes a float-encoded permutation back into order.
Definition utils.cpp:55
mono_float encodeOrderToFloat(int *order, int size)
Encodes a permutation (stored in order) into a single float.
Definition utils.cpp:32
void pcmToFloatData(float *float_data, const int16_t *pcm_data, int size)
Converts 16-bit PCM data to floating-point audio data.
Definition utils.cpp:94
force_inline poly_float interpolate(poly_float from, poly_float to, mono_float t)
Performs a linear interpolation between two poly_floats using a scalar t in [0..1].
Definition poly_utils.h:182
constexpr int kNumOscillators
Number of oscillators available in Vital.
Definition synth_constants.h:16
constexpr wchar_t kDefaultKeyboardOctaveUp
Default key for octave-up action in the computer keyboard layout.
Definition synth_constants.h:76
const std::string kSkinExtension
File extension for Vital skin/theme files.
Definition synth_constants.h:97
constexpr int kNotesPerOctave
Number of semitones per octave.
Definition common.h:51
const std::wstring kDefaultKeyboard
The default keyboard layout (QWERTY-based) mapping keys to notes.
Definition synth_constants.h:82
constexpr int kNumRandomLfos
Number of random LFO sources (random modulation generators).
Definition synth_constants.h:25
const std::string kWavetableExtensionsList
A semicolon-separated list of supported wavetable file extensions, including external formats like ....
Definition synth_constants.h:91
constexpr int kNumEnvelopes
Number of envelope generators in Vital.
Definition synth_constants.h:22
std::map< std::string, Value * > control_map
Maps parameter names to Value pointers representing synth control parameters.
Definition synth_types.h:214
constexpr int kNumOscillatorWaveFrames
Number of wave frames in each oscillator’s wavetable.
Definition synth_constants.h:19
constexpr wchar_t kDefaultKeyboardOctaveDown
Default key for octave-down action in the computer keyboard layout.
Definition synth_constants.h:79
constexpr int kNumLfos
Number of LFO sources available in the Vital synthesizer.
Definition synth_constants.h:13
constexpr int kMaxModulationConnections
Maximum number of modulation connections allowed.
Definition synth_constants.h:49
const std::string kLfoExtension
File extension for Vital LFO shape files.
Definition synth_constants.h:100
constexpr int kNumMacros
Number of macro controls available.
Definition synth_constants.h:28
const std::string kPresetExtension
File extension for Vital preset files.
Definition synth_constants.h:85
float mono_float
Definition common.h:33
Declares the Sample and SampleSource classes for loading, managing, and playing back audio samples in...
A structure representing a single modulation connection between a modulation source and a destination...
Definition synth_types.h:30
std::unique_ptr< ModulationConnectionProcessor > modulation_processor
Processor applying scaling/mapping.
Definition synth_types.h:75
std::string destination_name
The name of the destination parameter.
Definition synth_types.h:74
std::string source_name
The name of the modulation source.
Definition synth_types.h:73
Holds metadata about a single parameter (control) in the Vital synthesizer.
Definition synth_parameters.h:23
mono_float default_value
Default value for the parameter.
Definition synth_parameters.h:42