|
- /* Copyright 2013-2019 Matt Tytel
- *
- * vital is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * vital is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with vital. If not, see <http://www.gnu.org/licenses/>.
- */
-
- #include "load_save.h"
- #include "modulation_connection_processor.h"
- #include "sound_engine.h"
- #include "midi_manager.h"
- #include "sample_source.h"
- #include "synth_base.h"
- #include "synth_constants.h"
- #include "synth_oscillator.h"
-
- #define QUOTE(x) #x
- #define STRINGIFY(x) QUOTE(x)
-
- namespace {
- const std::string kLinuxUserDataDirectory = "~/.local/share/vital/";
- const std::string kAvailablePacksFile = "available_packs.json";
- const std::string kInstalledPacksFile = "packs.json";
-
- Time getBuildTime() {
- StringArray date_tokens;
- date_tokens.addTokens(STRINGIFY(BUILD_DATE), true);
- if (date_tokens.size() != 5)
- return Time::getCompilationDate();
-
- int year = date_tokens[0].getIntValue();
- int month = date_tokens[1].getIntValue() - 1;
- int day = date_tokens[2].getIntValue();
- int hour = date_tokens[3].getIntValue();
- int minute = date_tokens[4].getIntValue();
-
- return Time(year, month, day, hour, minute);
- }
- } // namespace
-
- const std::string LoadSave::kUserDirectoryName = "User";
- const std::string LoadSave::kPresetFolderName = "Presets";
- const std::string LoadSave::kWavetableFolderName = "Wavetables";
- const std::string LoadSave::kSkinFolderName = "Skins";
- const std::string LoadSave::kSampleFolderName = "Samples";
- const std::string LoadSave::kLfoFolderName = "LFOs";
-
- const std::string LoadSave::kAdditionalWavetableFoldersName = "wavetable_folders";
- const std::string LoadSave::kAdditionalSampleFoldersName = "sample_folders";
-
- void LoadSave::convertBufferToPcm(json& data, const std::string& field) {
- if (data.count(field) == 0)
- return;
-
- MemoryOutputStream decoded;
- std::string wave_data = data[field];
- Base64::convertFromBase64(decoded, wave_data);
- int size = static_cast<int>(decoded.getDataSize()) / sizeof(float);
- std::unique_ptr<float[]> float_data = std::make_unique<float[]>(size);
- memcpy(float_data.get(), decoded.getData(), size * sizeof(float));
- std::unique_ptr<int16_t[]> pcm_data = std::make_unique<int16_t[]>(size);
- vital::utils::floatToPcmData(pcm_data.get(), float_data.get(), size);
-
- String encoded = Base64::toBase64(pcm_data.get(), sizeof(int16_t) * size);
- data[field] = encoded.toStdString();
- }
-
- void LoadSave::convertPcmToFloatBuffer(json& data, const std::string& field) {
- if (data.count(field) == 0)
- return;
-
- MemoryOutputStream decoded;
- std::string wave_data = data[field];
- Base64::convertFromBase64(decoded, wave_data);
- int size = static_cast<int>(decoded.getDataSize()) / sizeof(int16_t);
- std::unique_ptr<int16_t[]> pcm_data = std::make_unique<int16_t[]>(size);
- memcpy(pcm_data.get(), decoded.getData(), size * sizeof(int16_t));
- std::unique_ptr<float[]> float_data = std::make_unique<float[]>(size);
- vital::utils::pcmToFloatData(float_data.get(), pcm_data.get(), size);
-
- String encoded = Base64::toBase64(float_data.get(), sizeof(float) * size);
- data[field] = encoded.toStdString();
- }
-
- json LoadSave::stateToJson(SynthBase* synth, const CriticalSection& critical_section) {
- json settings_data;
- vital::control_map& controls = synth->getControls();
- for (auto& control : controls)
- settings_data[control.first] = control.second->value();
-
- vital::Sample* sample = synth->getSample();
- if (sample)
- settings_data["sample"] = sample->stateToJson();
-
- json modulations;
- vital::ModulationConnectionBank& modulation_bank = synth->getModulationBank();
- for (int i = 0; i < vital::kMaxModulationConnections; ++i) {
- vital::ModulationConnection* connection = modulation_bank.atIndex(i);
- json modulation_data;
- modulation_data["source"] = connection->source_name;
- modulation_data["destination"] = connection->destination_name;
-
- LineGenerator* line_mapping = connection->modulation_processor->lineMapGenerator();
- if (!line_mapping->linear())
- modulation_data["line_mapping"] = line_mapping->stateToJson();
-
- modulations.push_back(modulation_data);
- }
-
- settings_data["modulations"] = modulations;
-
- if (synth->getWavetableCreator(0)) {
- json wavetables;
- for (int i = 0; i < vital::kNumOscillators; ++i) {
- WavetableCreator* wavetable_creator = synth->getWavetableCreator(i);
- wavetables.push_back(wavetable_creator->stateToJson());
- }
-
- settings_data["wavetables"] = wavetables;
- }
-
- json lfos;
- for (int i = 0; i < vital::kNumLfos; ++i) {
- LineGenerator* lfo_source = synth->getLfoSource(i);
- lfos.push_back(lfo_source->stateToJson());
- }
-
- settings_data["lfos"] = lfos;
-
- json data;
- data["synth_version"] = ProjectInfo::versionString;
- data["preset_name"] = synth->getPresetName().toStdString();
- data["author"] = synth->getAuthor().toStdString();
- data["comments"] = synth->getComments().toStdString();
- data["preset_style"] = synth->getStyle().toStdString();
- for (int i = 0; i < vital::kNumMacros; ++i) {
- std::string name = synth->getMacroName(i).toStdString();
- data["macro" + std::to_string(i + 1)] = name;
- }
- data["settings"] = settings_data;
- return data;
- }
-
- void LoadSave::loadControls(SynthBase* synth, const json& data) {
- vital::control_map controls = synth->getControls();
- for (auto& control : controls) {
- std::string name = control.first;
- if (data.count(name)) {
- vital::mono_float value = data[name];
- control.second->set(value);
- }
- else {
- vital::ValueDetails details = vital::Parameters::getDetails(name);
- control.second->set(details.default_value);
- }
- }
-
- synth->modWheelGuiChanged(controls["mod_wheel"]->value());
- }
-
- void LoadSave::loadModulations(SynthBase* synth, const json& modulations) {
- synth->clearModulations();
- vital::ModulationConnectionBank& modulation_bank = synth->getModulationBank();
- int index = 0;
- for (const json& modulation : modulations) {
- std::string source = modulation["source"];
- std::string destination = modulation["destination"];
- vital::ModulationConnection* connection = modulation_bank.atIndex(index);
- index++;
-
- if (synth->getEngine()->getModulationSource(source) == nullptr ||
- synth->getEngine()->getMonoModulationDestination(destination) == nullptr) {
- continue;
- }
-
- if (source.length() && destination.length()) {
- connection->source_name = source;
- connection->destination_name = destination;
- synth->connectModulation(connection);
- }
-
- if (modulation.count("line_mapping"))
- connection->modulation_processor->lineMapGenerator()->jsonToState(modulation["line_mapping"]);
- else
- connection->modulation_processor->lineMapGenerator()->initLinear();
- }
- }
-
- void LoadSave::loadSample(SynthBase* synth, const json& json_sample) {
- vital::Sample* sample = synth->getSample();
- if (sample)
- sample->jsonToState(json_sample);
- }
-
- void LoadSave::loadWavetables(SynthBase* synth, const json& wavetables) {
- if (synth->getWavetableCreator(0) == nullptr)
- return;
-
- int i = 0;
- for (const json& wavetable : wavetables) {
- WavetableCreator* wavetable_creator = synth->getWavetableCreator(i);
- wavetable_creator->jsonToState(wavetable);
- wavetable_creator->render();
- i++;
- }
- }
-
- void LoadSave::loadLfos(SynthBase* synth, const json& lfos) {
- int i = 0;
- for (const json& lfo : lfos) {
- LineGenerator* lfo_source = synth->getLfoSource(i);
- lfo_source->jsonToState(lfo);
- lfo_source->render();
- i++;
- }
- }
-
- void LoadSave::loadSaveState(std::map<std::string, String>& state, json data) {
- if (data.count("preset_name")) {
- std::string preset_name = data["preset_name"];
- state["preset_name"] = preset_name;
- }
-
- if (data.count("author")) {
- std::string author = data["author"];
- state["author"] = author;
- }
-
- if (data.count("comments")) {
- std::string comments = data["comments"];
- state["comments"] = comments;
- }
-
- if (data.count("preset_style")) {
- std::string style = data["preset_style"];
- state["style"] = style;
- }
-
- for (int i = 0; i < vital::kNumMacros; ++i) {
- std::string key = "macro" + std::to_string(i + 1);
- if (data.count(key)) {
- std::string name = data[key];
- state[key] = name;
- }
- else
- state[key] = "MACRO " + std::to_string(i + 1);
- }
- }
-
- void LoadSave::initSaveInfo(std::map<std::string, String>& save_info) {
- save_info["preset_name"] = "";
- save_info["author"] = "";
- save_info["comments"] = "";
- save_info["style"] = "";
-
- for (int i = 0; i < vital::kNumMacros; ++i)
- save_info["macro" + std::to_string(i + 1)] = "MACRO " + std::to_string(i + 1);
- }
-
- json LoadSave::updateFromOldVersion(json state) {
- json settings = state["settings"];
- json modulations = settings["modulations"];
- json sample = settings["sample"];
- json wavetables = settings["wavetables"];
-
- std::string version = state["synth_version"];
-
- if (compareVersionStrings(version, "0.2.0") < 0 || settings.count("sub_octave")) {
- int sub_waveform = settings["sub_waveform"];
- if (sub_waveform == 4)
- sub_waveform = 5;
- else if (sub_waveform == 5)
- sub_waveform = 4;
- settings["sub_waveform"] = sub_waveform;
-
- int sub_octave = settings["sub_octave"];
- settings["sub_transpose"] = vital::kNotesPerOctave * sub_octave;
-
- int osc_1_filter_routing = settings["osc_1_filter_routing"];
- int osc_2_filter_routing = settings["osc_2_filter_routing"];
- int sample_filter_routing = settings["sample_filter_routing"];
- int sub_filter_routing = settings["sub_filter_routing"];
- settings["filter_1_osc1_input"] = 1 - osc_1_filter_routing;
- settings["filter_1_osc2_input"] = 1 - osc_2_filter_routing;
- settings["filter_1_sample_input"] = 1 - sample_filter_routing;
- settings["filter_1_sub_input"] = 1 - sub_filter_routing;
- settings["filter_2_osc1_input"] = osc_1_filter_routing;
- settings["filter_2_osc2_input"] = osc_2_filter_routing;
- settings["filter_2_sample_input"] = sample_filter_routing;
- settings["filter_2_sub_input"] = sub_filter_routing;
-
- int filter_1_style = settings["filter_1_style"];
- if (filter_1_style == 2)
- filter_1_style = 3;
- else if (filter_1_style == 3)
- filter_1_style = 2;
- settings["filter_1_style"] = filter_1_style;
-
- int filter_2_style = settings["filter_2_style"];
- if (filter_2_style == 2)
- filter_2_style = 3;
- else if (filter_2_style == 3)
- filter_2_style = 2;
- settings["filter_2_style"] = filter_2_style;
- }
-
- if (compareVersionStrings(version, "0.2.1") < 0) {
- std::string env_start = "env_";
-
- for (int i = 0; i < vital::kNumEnvelopes; ++i) {
- std::string number = std::to_string(i + 1);
- std::string attack_string = env_start + number + "_attack";
- std::string decay_string = env_start + number + "_decay";
- std::string release_string = env_start + number + "_release";
- if (settings.count(attack_string) == 0)
- break;
-
- settings[attack_string] = std::pow(settings[attack_string], 1.0f / 1.5f);
- settings[decay_string] = std::pow(settings[decay_string], 1.0f / 1.5f);
- settings[release_string] = std::pow(settings[release_string], 1.0f / 1.5f);
- }
-
- if (settings.count("wave_tables"))
- settings["wavetables"] = settings["wave_tables"];
- }
-
- wavetables = settings["wavetables"];
-
- if (compareVersionStrings(version, "0.2.4") < 0) {
- int portamento_type = settings["portamento_type"];
- settings["portamento_force"] = std::max(0, portamento_type - 1);
-
- if (portamento_type == 0)
- settings["portamento_time"] = -10.0f;
- }
-
- if (compareVersionStrings(version, "0.2.5") < 0) {
- std::string env_start = "env_";
-
- for (int i = 0; i < vital::kNumEnvelopes; ++i) {
- std::string number = std::to_string(i + 1);
- std::string attack_string = env_start + number + "_attack";
- std::string decay_string = env_start + number + "_decay";
- std::string release_string = env_start + number + "_release";
- if (settings.count(attack_string) == 0)
- break;
-
- float adjust_power = 3.0f / 4.0f;
- settings[attack_string] = std::pow(settings[attack_string], adjust_power);
- settings[decay_string] = std::pow(settings[decay_string], adjust_power);
- settings[release_string] = std::pow(settings[release_string], adjust_power);
- }
- }
-
- if (compareVersionStrings(version, "0.2.6") < 0) {
- std::string lfo_start = "lfo_";
-
- for (int i = 0; i < vital::kNumLfos; ++i) {
- std::string number = std::to_string(i + 1);
- std::string fade_string = lfo_start + number + "_fade_time";
- std::string delay_string = lfo_start + number + "_delay_time";
- settings[fade_string] = 0.0f;
- settings[delay_string] = 0.0f;
- }
- }
-
- if (compareVersionStrings(version, "0.2.7") < 0) {
- static constexpr float adjustment = 0.70710678119f;
- float osc_1_level = settings["osc_1_level"];
- float osc_2_level = settings["osc_2_level"];
- float sub_level = settings["sub_level"];
- float sample_level = settings["sample_level"];
- osc_1_level = adjustment * osc_1_level * osc_1_level;
- osc_2_level = adjustment * osc_2_level * osc_2_level;
- sub_level = adjustment * sub_level * sub_level;
- sample_level = adjustment * sample_level * sample_level;
-
- settings["osc_1_level"] = sqrtf(osc_1_level);
- settings["osc_2_level"] = sqrtf(osc_2_level);
- settings["sub_level"] = sqrtf(sub_level);
- settings["sample_level"] = sqrtf(sample_level);
- }
-
- if (compareVersionStrings(version, "0.3.0") < 0) {
- float reverb_damping = settings["reverb_damping"];
- float reverb_feedback = settings["reverb_feedback"];
- settings["decay_time"] = (reverb_feedback - 0.8f) * 10.0f;
- settings["reverb_high_shelf_gain"] = -reverb_damping * 4.0f;
- settings["reverb_pre_high_cutoff"] = 128.0f;
-
- json new_modulations;
- for (json& modulation : modulations) {
- if (modulation["destination"] == "reverb_damping")
- modulation["destination"] = "reverb_high_shelf_gain";
- if (modulation["destination"] == "reverb_feedback")
- modulation["destination"] = "reverb_decay_time";
-
- new_modulations.push_back(modulation);
- }
- modulations = new_modulations;
- }
-
- if (compareVersionStrings(version, "0.3.1") < 0) {
- float sample_transpose = settings["sample_transpose"];
- float sample_keytrack = settings["sample_keytrack"];
- if (sample_keytrack)
- settings["sample_transpose"] = sample_transpose + 28.0f;
- }
-
- if (compareVersionStrings(version, "0.3.2") < 0) {
- float osc_1_transpose = settings["osc_1_transpose"];
- float osc_1_midi_track = settings["osc_1_midi_track"];
- if (osc_1_midi_track == 0.0f)
- settings["osc_1_transpose"] = osc_1_transpose - 48.0f;
-
- float osc_2_transpose = settings["osc_2_transpose"];
- float osc_2_midi_track = settings["osc_2_midi_track"];
- if (osc_2_midi_track == 0.0f)
- settings["osc_2_transpose"] = osc_2_transpose - 48.0f;
- }
-
- if (compareVersionStrings(version, "0.3.4") < 0) {
- float float_order = settings["effect_chain_order"];
- int effect_order[vital::constants::kNumEffects];
- vital::utils::decodeFloatToOrder(effect_order, float_order, vital::constants::kNumEffects - 1);
- for (int i = 0; i < vital::constants::kNumEffects - 1; ++i) {
- if (effect_order[i] >= vital::constants::kFilterFx)
- effect_order[i] += 1;
- }
- effect_order[vital::constants::kNumEffects - 1] = vital::constants::kFilterFx;
- settings["effect_chain_order"] = vital::utils::encodeOrderToFloat(effect_order, vital::constants::kNumEffects);
- }
-
- if (compareVersionStrings(version, "0.3.5") < 0) {
- float osc_1_distortion_type = settings["osc_1_distortion_type"];
- float osc_2_distortion_type = settings["osc_2_distortion_type"];
- if (osc_1_distortion_type >= 10.0f)
- settings["osc_1_distortion_type"] = osc_1_distortion_type + 1.0f;
- if (osc_2_distortion_type >= 10.0f)
- settings["osc_2_distortion_type"] = osc_2_distortion_type + 1.0f;
- }
-
- if (compareVersionStrings(version, "0.3.6") < 0) {
- std::string lfo_start = "lfo_";
-
- for (int i = 0; i < vital::kNumLfos; ++i) {
- std::string sync_type_string = lfo_start + std::to_string(i + 1) + "_sync_type";
- if (settings.count(sync_type_string)) {
- float value = settings[sync_type_string];
- if (value >= 2.0f)
- settings[sync_type_string] = value - 1.0f;
- }
- }
- }
-
- if (compareVersionStrings(version, "0.3.7") < 0) {
- convertBufferToPcm(sample, "samples");
- convertBufferToPcm(sample, "samples_stereo");
- }
-
- if (compareVersionStrings(version, "0.4.1") < 0) {
- bool update = false;
- json new_modulations;
- for (json& modulation : modulations) {
- if (modulation["source"] == "perlin") {
- update = true;
- modulation["source"] = "random_1";
- }
-
- new_modulations.push_back(modulation);
- }
-
- if (update) {
- modulations = new_modulations;
- settings["random_1_sync"] = 0.0f;
- settings["random_1_frequency"] = 1.65149612947f;
- settings["random_1_stereo"] = 1.0f;
- }
- }
-
- if (compareVersionStrings(version, "0.4.3") < 0) {
- float osc_1_distortion_type = settings["osc_1_distortion_type"];
- float osc_1_distortion_amount = settings["osc_1_distortion_amount"];
- if (osc_1_distortion_type == vital::SynthOscillator::kFormant) {
- settings["osc_1_distortion_amount"] = 0.5f + 0.5f * osc_1_distortion_amount;
-
- int index = 1;
- for (json& modulation : modulations) {
- if (modulation["destination"] == "osc_1_distortion_amount") {
- std::string amount_string = "modulation_" + std::to_string(index) + "_amount";
- float last_amount = settings[amount_string];
- settings[amount_string] = 0.5f * last_amount;
- }
-
- index++;
- }
- }
-
- float osc_2_distortion_type = settings["osc_2_distortion_type"];
- float osc_2_distortion_amount = settings["osc_2_distortion_amount"];
- if (osc_2_distortion_type == vital::SynthOscillator::kFormant) {
- settings["osc_2_distortion_amount"] = 0.5f + 0.5f * osc_2_distortion_amount;
-
- int index = 1;
- for (json& modulation : modulations) {
- if (modulation["destination"] == "osc_2_distortion_amount") {
- std::string amount_string = "modulation_" + std::to_string(index) + "_amount";
- float last_amount = settings[amount_string];
- settings[amount_string] = 0.5f * last_amount;
- }
-
- index++;
- }
- }
- }
-
- if (compareVersionStrings(version, "0.4.4") < 0) {
- float osc_1_distortion_type = settings["osc_1_distortion_type"];
- float osc_1_distortion_amount = settings["osc_1_distortion_amount"];
- if (osc_1_distortion_type == vital::SynthOscillator::kSync) {
- settings["osc_1_distortion_amount"] = 0.5f + 0.5f * osc_1_distortion_amount;
-
- int index = 1;
- for (json& modulation : modulations) {
- if (modulation["destination"] == "osc_1_distortion_amount") {
- std::string amount_string = "modulation_" + std::to_string(index) + "_amount";
- float last_amount = settings[amount_string];
- settings[amount_string] = 0.5f * last_amount;
- }
-
- index++;
- }
- }
-
- float osc_2_distortion_type = settings["osc_2_distortion_type"];
- float osc_2_distortion_amount = settings["osc_2_distortion_amount"];
- if (osc_2_distortion_type == vital::SynthOscillator::kSync) {
- settings["osc_2_distortion_amount"] = 0.5f + 0.5f * osc_2_distortion_amount;
-
- int index = 1;
- for (json& modulation : modulations) {
- if (modulation["destination"] == "osc_2_distortion_amount") {
- std::string amount_string = "modulation_" + std::to_string(index) + "_amount";
- float last_amount = settings[amount_string];
- settings[amount_string] = 0.5f * last_amount;
- }
-
- index++;
- }
- }
- }
-
- if (compareVersionStrings(version, "0.4.5") < 0) {
- float compressor_low_band = settings["compressor_low_band"];
- float compressor_high_band = settings["compressor_high_band"];
- if (compressor_low_band && compressor_high_band)
- settings["compressor_enabled_bands"] = 0;
- else if (compressor_low_band)
- settings["compressor_enabled_bands"] = 1;
- else if (compressor_high_band)
- settings["compressor_enabled_bands"] = 2;
- else
- settings["compressor_enabled_bands"] = 3;
- }
-
- if (compareVersionStrings(version, "0.4.7") < 0 && settings.count("osc_1_distortion_type")) {
- static const int kRemapResolution = 32;
-
- float osc_1_distortion_type = settings["osc_1_distortion_type"];
- if (osc_1_distortion_type)
- settings["osc_1_distortion_type"] = osc_1_distortion_type - 1.0f;
-
- float osc_2_distortion_type = settings["osc_2_distortion_type"];
- if (osc_2_distortion_type)
- settings["osc_2_distortion_type"] = osc_2_distortion_type - 1.0f;
-
- if (osc_1_distortion_type == 1.0f)
- settings["osc_1_spectral_morph_type"] = vital::SynthOscillator::kLowPass;
-
- if (osc_2_distortion_type == 1.0f)
- settings["osc_2_spectral_morph_type"] = vital::SynthOscillator::kLowPass;
-
- json new_modulations;
- for (json& modulation : modulations) {
- if (osc_1_distortion_type == 1.0f && modulation["destination"] == "osc_1_distortion_amount")
- modulation["destination"] = "osc_1_spectral_morph_amount";
- else if (osc_2_distortion_type == 1.0f && modulation["destination"] == "osc_2_distortion_amount")
- modulation["destination"] = "osc_2_spectral_morph_amount";
-
- new_modulations.push_back(modulation);
- }
-
- osc_1_distortion_type = settings["osc_1_distortion_type"];
- osc_2_distortion_type = settings["osc_2_distortion_type"];
- if (osc_1_distortion_type == 7 || osc_1_distortion_type == 8 || osc_1_distortion_type == 9) {
- float original_fm_amount = settings["osc_1_distortion_amount"];
- float new_fm_amount = std::pow(original_fm_amount, 1.0f / 2.0f);
- settings["osc_1_distortion_amount"] = new_fm_amount;
-
- int index = 1;
- for (json& modulation : new_modulations) {
- if (modulation["destination"] == "osc_1_distortion_amount") {
- std::string number = std::to_string(index);
- std::string amount_string = "modulation_" + number + "_amount";
- float last_amount = settings[amount_string];
- if (last_amount == 0.0f)
- continue;
-
- bool bipolar = settings["modulation_" + number + "_bipolar"] != 0.0f;
- float min = std::min(original_fm_amount, original_fm_amount + last_amount);
- float max = std::max(original_fm_amount, original_fm_amount + last_amount);
-
- if (bipolar) {
- min = std::min(original_fm_amount + last_amount * 0.5f, original_fm_amount - last_amount * 0.5f);
- max = std::max(original_fm_amount + last_amount * 0.5f, original_fm_amount - last_amount * 0.5f);
- }
-
- float min_target = std::pow(min, 1.0f / 2.0f);
- float max_target = std::pow(max, 1.0f / 2.0f);
- float new_amount = max_target - min_target;
- if (bipolar)
- new_amount = 2.0f * std::max(new_fm_amount - min_target, max_target - new_fm_amount);
- settings[amount_string] = new_amount;
-
- LineGenerator scale;
- scale.initLinear();
- scale.setNumPoints(kRemapResolution);
- for (int i = 0; i < kRemapResolution; ++i) {
- float t = i / (kRemapResolution - 1.0f);
- float old_value = vital::utils::interpolate(min, max, t);
- float adjusted_old_value = std::pow(old_value, 1.0f / 2.0f);
- float y = 1.0f - (adjusted_old_value - min_target) / new_amount;
- scale.setPoint(i, std::pair<float, float>(t, y));
- }
- modulation["line_mapping"] = scale.stateToJson();
- }
- index++;
- }
- }
-
- if (osc_2_distortion_type == 7 || osc_2_distortion_type == 8 || osc_2_distortion_type == 9) {
- float original_fm_amount = settings["osc_2_distortion_amount"];
- float new_fm_amount = std::pow(original_fm_amount, 1.0f / 2.0f);
- settings["osc_2_distortion_amount"] = new_fm_amount;
-
- int index = 1;
- for (json& modulation : new_modulations) {
- if (modulation["destination"] == "osc_2_distortion_amount") {
- std::string number = std::to_string(index);
- std::string amount_string = "modulation_" + number + "_amount";
- float last_amount = settings[amount_string];
- if (last_amount == 0.0f)
- continue;
-
- bool bipolar = settings["modulation_" + number + "_bipolar"] != 0.0f;
- float min = std::min(original_fm_amount, original_fm_amount + last_amount);
- float max = std::max(original_fm_amount, original_fm_amount + last_amount);
-
- if (bipolar) {
- min = std::min(original_fm_amount + last_amount * 0.5f, original_fm_amount - last_amount * 0.5f);
- max = std::max(original_fm_amount + last_amount * 0.5f, original_fm_amount - last_amount * 0.5f);
- }
-
- float min_target = std::pow(min, 1.0f / 2.0f);
- float max_target = std::pow(max, 1.0f / 2.0f);
- float new_amount = max_target - min_target;
- if (bipolar)
- new_amount = 2.0f * std::max(new_fm_amount - min_target, max_target - new_fm_amount);
- settings[amount_string] = new_amount;
-
- LineGenerator scale;
- scale.initLinear();
- scale.setNumPoints(kRemapResolution);
- for (int i = 0; i < kRemapResolution; ++i) {
- float t = i / (kRemapResolution - 1.0f);
- float old_value = vital::utils::interpolate(min, max, t);
- float adjusted_old_value = std::pow(old_value, 1.0f / 2.0f);
- float y = 1.0f - (adjusted_old_value - min_target) / new_amount;
- scale.setPoint(i, std::pair<float, float>(t, y));
- }
- modulation["line_mapping"] = scale.stateToJson();
- }
- index++;
- }
- }
-
- modulations = new_modulations;
- }
-
- if (compareVersionStrings(version, "0.5.0") < 0 && settings.count("sub_on")) {
- settings["osc_3_on"] = settings["sub_on"];
- settings["osc_3_level"] = settings["sub_level"];
- settings["osc_3_pan"] = settings["sub_pan"];
- settings["osc_3_transpose"] = settings["sub_transpose"];
-
- if (settings.count("sub_transpose_quantize"))
- settings["osc_3_transpose_quantize"] = settings["sub_transpose_quantize"];
-
- settings["osc_3_tune"] = settings["sub_tune"];
- settings["osc_3_phase"] = 0.25f;
- settings["osc_3_random_phase"] = 0.0f;
-
- float sub_waveform = settings["sub_waveform"];
- settings["osc_3_wave_frame"] = sub_waveform * 257.0f / 6.0f;
-
- float sub_filter1 = settings["filter_1_sub_input"];
- float sub_filter2 = settings["filter_2_sub_input"];
- float sub_direct_out = settings["sub_direct_out"];
- if (sub_direct_out)
- settings["osc_3_destination"] = 4.0f;
- else if (sub_filter1 && sub_filter2)
- settings["osc_3_destination"] = 2.0f;
- else if (sub_filter2)
- settings["osc_3_destination"] = 1.0f;
- else if (sub_filter1)
- settings["osc_3_destination"] = 0.0f;
- else
- settings["osc_3_destination"] = 3.0f;
-
- float osc1_filter1 = settings["filter_1_osc1_input"];
- float osc1_filter2 = settings["filter_2_osc1_input"];
- if (osc1_filter1 && osc1_filter2)
- settings["osc_1_destination"] = 2.0f;
- else if (osc1_filter2)
- settings["osc_1_destination"] = 1.0f;
- else if (osc1_filter1)
- settings["osc_1_destination"] = 0.0f;
- else
- settings["osc_1_destination"] = 3.0f;
-
- float osc2_filter1 = settings["filter_1_osc2_input"];
- float osc2_filter2 = settings["filter_2_osc2_input"];
- if (osc2_filter1 && osc2_filter2)
- settings["osc_2_destination"] = 2.0f;
- else if (osc2_filter2)
- settings["osc_2_destination"] = 1.0f;
- else if (osc2_filter1)
- settings["osc_2_destination"] = 0.0f;
- else
- settings["osc_2_destination"] = 3.0f;
-
- float sample_filter1 = settings["filter_1_sample_input"];
- float sample_filter2 = settings["filter_2_sample_input"];
- if (sample_filter1 && sample_filter2)
- settings["sample_destination"] = 2.0f;
- else if (sample_filter2)
- settings["sample_destination"] = 1.0f;
- else if (sample_filter1)
- settings["sample_destination"] = 0.0f;
- else
- settings["sample_destination"] = 3.0f;
-
- vital::Wavetable wavetable(vital::kNumOscillatorWaveFrames);
- WavetableCreator wavetable_creator(&wavetable);
- wavetable_creator.initPredefinedWaves();
- wavetable_creator.setName("Sub");
-
- json new_wavetables;
- for (int i = (int)wavetables.size() - 1; i >= 0; --i)
- new_wavetables.push_back(wavetables[i]);
-
- new_wavetables.push_back(wavetable_creator.stateToJson());
- settings["wavetables"] = new_wavetables;
-
- json new_modulations;
- for (json& modulation : modulations) {
- if (modulation["destination"] == "sub_transpose")
- modulation["destination"] = "osc_3_transpose";
- else if (modulation["destination"] == "sub_tune")
- modulation["destination"] = "osc_3_tune";
- else if (modulation["destination"] == "sub_level")
- modulation["destination"] = "osc_3_level";
- else if (modulation["destination"] == "sub_pan")
- modulation["destination"] = "osc_3_pan";
-
- new_modulations.push_back(modulation);
- }
-
- modulations = new_modulations;
- }
-
- if (compareVersionStrings(version, "0.5.5") < 0) {
- float flanger_tempo = settings["flanger_tempo"];
- settings["flanger_tempo"] = flanger_tempo + 1.0f;
-
- float phaser_tempo = settings["phaser_tempo"];
- settings["phaser_tempo"] = phaser_tempo + 1.0f;
-
- float chorus_tempo = settings["chorus_tempo"];
- settings["chorus_tempo"] = chorus_tempo + 1.0f;
-
- float delay_tempo = settings["delay_tempo"];
- settings["delay_tempo"] = delay_tempo + 1.0f;
-
- std::string lfo_start = "lfo_";
- for (int i = 0; i < vital::kNumLfos; ++i) {
- std::string tempo_string = lfo_start + std::to_string(i + 1) + "_tempo";
- if (settings.count(tempo_string)) {
- float tempo = settings[tempo_string];
- settings[tempo_string] = tempo + 1.0f;
- }
- }
-
- std::string random_start = "random_";
- for (int i = 0; i < vital::kNumRandomLfos; ++i) {
- std::string tempo_string = random_start + std::to_string(i + 1) + "_tempo";
- if (settings.count(tempo_string)) {
- float tempo = settings[tempo_string];
- settings[tempo_string] = tempo + 1.0f;
- }
- }
- }
-
- if (compareVersionStrings(version, "0.5.7") < 0) {
- settings["delay_aux_sync"] = settings["delay_sync"];
- settings["delay_aux_frequency"] = settings["delay_frequency"];
- settings["delay_aux_tempo"] = settings["delay_tempo"];
-
- float style = settings["delay_style"];
- if (style)
- settings["delay_style"] = style + 1.0f;
- }
-
- if (compareVersionStrings(version, "0.5.8") < 0)
- settings["chorus_damping"] = 1.0f;
-
- if (compareVersionStrings(version, "0.6.5") < 0) {
- settings["stereo_mode"] = 1.0f;
- float routing = settings["stereo_routing"];
- routing *= 0.125f;
- if (routing < 0.0f)
- settings["stereo_routing"] = 1.0f - routing;
- else
- settings["stereo_routing"] = routing;
- }
-
- if (compareVersionStrings(version, "0.6.6") < 0) {
- float stereo_mode = settings["stereo_mode"];
- float routing = settings["stereo_routing"];
- if (stereo_mode == 0.0f)
- settings["stereo_routing"] = 1.0f - routing;
- }
-
- if (compareVersionStrings(version, "0.6.7") < 0) {
- float chorus_damping = settings["chorus_damping"];
- settings["chorus_cutoff"] = 20.0f;
- settings["chorus_spread"] = chorus_damping;
-
- json new_modulations;
- for (json& modulation : modulations) {
- if (modulation["destination"] == "chorus_damping")
- modulation["destination"] = "chorus_spread";
-
- new_modulations.push_back(modulation);
- }
- modulations = new_modulations;
- }
-
- if (compareVersionStrings(version, "0.7.1") < 0) {
- float osc_1_spectral_morph_type = 0.0f;
- if (settings.count("osc_1_spectral_morph_type"))
- osc_1_spectral_morph_type = settings["osc_1_spectral_morph_type"];
-
- float osc_2_spectral_morph_type = 0.0f;
- if (settings.count("osc_2_spectral_morph_type"))
- osc_2_spectral_morph_type = settings["osc_2_spectral_morph_type"];
-
- if (osc_1_spectral_morph_type == 9.0f) {
- float osc_1_spectral_morph_amount = settings["osc_1_spectral_morph_amount"];
- settings["osc_1_spectral_morph_amount"] = -0.5f * osc_1_spectral_morph_amount + 0.5f;
-
- int index = 1;
- for (json& modulation : modulations) {
- if (modulation["destination"] == "osc_1_spectral_morph_amount") {
- std::string name = "modulation_" + std::to_string(index) + "_amount";
- float modulation_amount = settings[name];
- settings[name] = modulation_amount * -0.5f;
- }
-
- index++;
- }
- }
- if (osc_2_spectral_morph_type == 9.0f) {
- float osc_2_spectral_morph_amount = settings["osc_2_spectral_morph_amount"];
- settings["osc_2_spectral_morph_amount"] = -0.5f * osc_2_spectral_morph_amount + 0.5f;
-
- int index = 1;
- for (json& modulation : modulations) {
- if (modulation["destination"] == "osc_2_spectral_morph_amount") {
- std::string name = "modulation_" + std::to_string(index) + "_amount";
- float modulation_amount = settings[name];
- settings[name] = modulation_amount * -0.5f;
- }
-
- index++;
- }
- }
- }
-
- if (compareVersionStrings(version, "0.7.5") < 0) {
- static constexpr float kFlangerCenterMultiply = 48.0f / 128.0f;
- static constexpr float kFlangerCenterOffset = 53.69f;
- static constexpr float kPhaserCenterMultiply = 48.0f / 128.0f;
-
- if (settings.count("flanger_center")) {
- float flanger_center = settings["flanger_center"];
- settings["flanger_center"] = flanger_center + kFlangerCenterOffset;
- }
-
- int index = 1;
- for (json& modulation : modulations) {
- if (modulation["destination"] == "flanger_center") {
- std::string name = "modulation_" + std::to_string(index) + "_amount";
- float modulation_amount = settings[name];
- settings[name] = modulation_amount * kFlangerCenterMultiply;
- }
- if (modulation["destination"] == "phaser_center") {
- std::string name = "modulation_" + std::to_string(index) + "_amount";
- float modulation_amount = settings[name];
- settings[name] = modulation_amount * kPhaserCenterMultiply;
- }
-
- index++;
- }
- }
-
- if (compareVersionStrings(version, "0.7.6") < 0) {
- int filter_1_model = settings["filter_1_model"];
- int filter_2_model = settings["filter_2_model"];
-
- if (filter_1_model == 6) {
- int filter_1_style = settings["filter_1_style"];
- if (filter_1_style == 1)
- settings["filter_1_style"] = 3;
- }
-
- if (filter_2_model == 6) {
- int filter_2_style = settings["filter_2_style"];
- if (filter_2_style == 1)
- settings["filter_2_style"] = 3;
- }
-
- if (settings.count("filter_fx_model")) {
- int filter_fx_model = settings["filter_fx_model"];
- if (filter_fx_model == 6) {
- int filter_fx_style = settings["filter_fx_style"];
- if (filter_fx_style == 1)
- settings["filter_fx_style"] = 3;
- }
- }
- }
-
- if (compareVersionStrings(version, "0.7.6") < 0) {
- if (settings.count("osc_1_spectral_morph_type")) {
- float osc_1_spectral_morph_type = settings["osc_1_spectral_morph_type"];
- if (osc_1_spectral_morph_type == 10.0f)
- settings["osc_1_spectral_morph_type"] = 7.0f;
- }
-
- if (settings.count("osc_2_spectral_morph_type")) {
- float osc_2_spectral_morph_type = settings["osc_2_spectral_morph_type"];
- if (osc_2_spectral_morph_type == 10.0f)
- settings["osc_2_spectral_morph_type"] = 7.0f;
- }
-
- if (settings.count("osc_3_spectral_morph_type")) {
- float osc_3_spectral_morph_type = settings["osc_3_spectral_morph_type"];
- if (osc_3_spectral_morph_type == 10.0f)
- settings["osc_3_spectral_morph_type"] = 7.0f;
- }
- }
-
- if (compareVersionStrings(version, "0.8.1") < 0) {
- for (int i = 0; i < vital::kNumLfos; ++i) {
- std::string name = "lfo_" + std::to_string(i) + "_smooth_mode";
- settings[name] = 0.0f;
- }
- }
-
- if (compareVersionStrings(version, "0.9.0") < 0) {
- float filter_1_model = settings["filter_1_model"];
- if (filter_1_model == 4) {
- settings["filter_1_blend"] = 0.0f;
- settings["filter_1_style"] = 0.0f;
- int index = 1;
- for (json& modulation : modulations) {
- if (modulation["destination"] == "filter_1_blend") {
- std::string name = "modulation_" + std::to_string(index) + "_amount";
- settings[name] = 0.0f;
- }
-
- index++;
- }
- }
-
- float filter_2_model = settings["filter_2_model"];
- if (filter_2_model == 4) {
- settings["filter_2_blend"] = 0.0f;
- settings["filter_2_style"] = 0.0f;
- int index = 1;
- for (json& modulation : modulations) {
- if (modulation["destination"] == "filter_2_blend") {
- std::string name = "modulation_" + std::to_string(index) + "_amount";
- settings[name] = 0.0f;
- }
-
- index++;
- }
- }
- }
-
- settings["modulations"] = modulations;
- settings["sample"] = sample;
- state["settings"] = settings;
- return state;
- }
-
- bool LoadSave::jsonToState(SynthBase* synth, std::map<std::string, String>& save_info, json data) {
- std::string version = data["synth_version"];
-
- int compare_feature_versions = compareFeatureVersionStrings(version, ProjectInfo::versionString);
- if (compare_feature_versions > 0)
- return false;
-
- int compare_versions = compareVersionStrings(version, ProjectInfo::versionString);
- if (compare_versions < 0 || data["settings"].count("sub_octave"))
- data = updateFromOldVersion(data);
-
- json settings = data["settings"];
- json modulations = settings["modulations"];
- json sample = settings["sample"];
- json wavetables = settings["wavetables"];
- json lfos = settings["lfos"];
-
- loadControls(synth, settings);
- loadModulations(synth, modulations);
- loadSample(synth, sample);
- loadWavetables(synth, wavetables);
- loadLfos(synth, lfos);
- loadSaveState(save_info, data);
- synth->checkOversampling();
-
- return true;
- }
-
- String LoadSave::getAuthorFromFile(const File& file) {
- static constexpr int kMaxCharacters = 40;
- static constexpr int kMinSize = 60;
- FileInputStream file_stream(file);
-
- if (file_stream.getTotalLength() < kMinSize)
- return "";
-
- file_stream.readByte();
- file_stream.readByte();
- MemoryBlock author_memory_block;
- file_stream.readIntoMemoryBlock(author_memory_block, 6);
-
- char end_quote = file_stream.readByte();
- char colon = file_stream.readByte();
- char begin_quote = file_stream.readByte();
- if (author_memory_block.toString() != "author" || end_quote != '"' || colon != ':' || begin_quote != '"') {
- try {
- json parsed_json_state = json::parse(file.loadFileAsString().toStdString(), nullptr, false);
- return getAuthor(parsed_json_state);
- }
- catch (const json::exception& e) {
- return "";
- }
- }
-
- MemoryBlock name_memory_block;
- file_stream.readIntoMemoryBlock(name_memory_block, kMaxCharacters);
- String name = name_memory_block.toString();
-
- if (!name.contains("\""))
- return name.toStdString();
-
- StringArray tokens;
- tokens.addTokens(name, "\"", "");
-
- return tokens[0];
- }
-
- String LoadSave::getStyleFromFile(const File& file) {
- static constexpr int kMinSize = 5000;
- FileInputStream file_stream(file);
-
- if (file_stream.getTotalLength() < kMinSize)
- return "";
-
- MemoryBlock style_memory_block;
- file_stream.readIntoMemoryBlock(style_memory_block, kMinSize);
-
- StringArray tokens;
- tokens.addTokens(style_memory_block.toString(), "\"", "");
- bool found_style = false;
- for (String token : tokens) {
- if (found_style && token.trim() != ":")
- return token;
- if (token == "preset_style")
- found_style = true;
- }
-
- return "";
- }
-
- std::string LoadSave::getAuthor(json data) {
- if (data.count("author"))
- return data["author"];
- return "";
- }
-
- std::string LoadSave::getLicense(json data) {
- if (data.count("license"))
- return data["license"];
- return "";
- }
-
- File LoadSave::getConfigFile() {
- #if defined(JUCE_DATA_STRUCTURES_H_INCLUDED)
- PropertiesFile::Options config_options;
- config_options.applicationName = "Vial";
- config_options.osxLibrarySubFolder = "Application Support";
- config_options.filenameSuffix = "config";
-
- #ifdef LINUX
- config_options.folderName = "." + String(ProjectInfo::projectName).toLowerCase();
- #else
- config_options.folderName = String(ProjectInfo::projectName).toLowerCase();
- #endif
-
- return config_options.getDefaultFile();
- #else
- return File();
- #endif
- }
-
- void LoadSave::writeCrashLog(String crash_log) {
- File data_dir = getDataDirectory();
- if (!data_dir.exists() || !data_dir.isDirectory())
- return;
- File file = data_dir.getChildFile("crash.txt");
- file.replaceWithText(crash_log);
- }
-
- void LoadSave::writeErrorLog(String error_log) {
- File data_dir = getDataDirectory();
- if (!data_dir.exists() || !data_dir.isDirectory())
- return;
-
- File file = getDataDirectory().getChildFile("errors.txt");
- file.appendText(error_log + "\n");
- }
-
- File LoadSave::getFavoritesFile() {
- #if defined(JUCE_DATA_STRUCTURES_H_INCLUDED)
- PropertiesFile::Options config_options;
- config_options.applicationName = "Vial";
- config_options.osxLibrarySubFolder = "Application Support";
- config_options.filenameSuffix = "favorites";
-
- #ifdef LINUX
- config_options.folderName = "." + String(ProjectInfo::projectName).toLowerCase();
- #else
- config_options.folderName = String(ProjectInfo::projectName).toLowerCase();
- #endif
-
- return config_options.getDefaultFile();
- #else
- return File();
- #endif
- }
-
- File LoadSave::getDefaultSkin() {
- #if defined(JUCE_DATA_STRUCTURES_H_INCLUDED)
- PropertiesFile::Options config_options;
- config_options.applicationName = "Vial";
- config_options.osxLibrarySubFolder = "Application Support";
- config_options.filenameSuffix = "skin";
-
- #ifdef LINUX
- config_options.folderName = "." + String(ProjectInfo::projectName).toLowerCase();
- #else
- config_options.folderName = String(ProjectInfo::projectName).toLowerCase();
- #endif
-
- return config_options.getDefaultFile();
- #else
- return File();
- #endif
- }
-
- json LoadSave::getConfigJson() {
- File config_file = getConfigFile();
- if (!config_file.exists())
- return json();
-
- try {
- json parsed = json::parse(config_file.loadFileAsString().toStdString(), nullptr, false);
- if (parsed.is_discarded())
- return json();
- return parsed;
- }
- catch (const json::exception& e) {
- return json();
- }
- }
-
- json LoadSave::getFavoritesJson() {
- File favorites_file = getFavoritesFile();
- if (!favorites_file.exists())
- return json();
-
- try {
- json parsed = json::parse(favorites_file.loadFileAsString().toStdString(), nullptr, false);
- if (parsed.is_discarded())
- return json();
- return parsed;
- }
- catch (const json::exception& e) {
- return json();
- }
- }
-
- void LoadSave::addFavorite(const File& new_favorite) {
- json favorites = getFavoritesJson();
- favorites[new_favorite.getFullPathName().toStdString()] = 1;
- saveJsonToFavorites(favorites);
- }
-
- void LoadSave::removeFavorite(const File& old_favorite) {
- json favorites = getFavoritesJson();
- std::string path = old_favorite.getFullPathName().toStdString();
-
- if (favorites.count(path)) {
- favorites.erase(path);
- saveJsonToFavorites(favorites);
- }
- }
-
- std::set<std::string> LoadSave::getFavorites() {
- json favorites_json = getFavoritesJson();
-
- std::set<std::string> favorites;
- for (auto& pair : favorites_json.items())
- favorites.insert(pair.key());
-
- return favorites;
- }
-
- void LoadSave::saveJsonToConfig(json config_state) {
- File config_file = getConfigFile();
-
- if (!config_file.exists())
- config_file.create();
- config_file.replaceWithText(config_state.dump());
- }
-
- void LoadSave::saveJsonToFavorites(json favorites_json) {
- File favorites_file = getFavoritesFile();
-
- if (!favorites_file.exists())
- favorites_file.create();
- favorites_file.replaceWithText(favorites_json.dump());
- }
-
- void LoadSave::saveAuthor(std::string author) {
- json data = getConfigJson();
-
- data["author"] = author;
- saveJsonToConfig(data);
- }
-
- void LoadSave::savePreferredTTWTLanguage(std::string language) {
- json data = getConfigJson();
- data["ttwt_language"] = language;
- saveJsonToConfig(data);
- }
-
- void LoadSave::saveVersionConfig() {
- json data = getConfigJson();
-
- data["synth_version"] = ProjectInfo::versionString;
- saveJsonToConfig(data);
- }
-
- void LoadSave::saveContentVersion(std::string version) {
- json data = getConfigJson();
-
- data["content_version"] = version;
- saveJsonToConfig(data);
- }
-
- void LoadSave::saveUpdateCheckConfig(bool check_for_updates) {
- json data = getConfigJson();
- data["check_for_updates"] = check_for_updates;
- saveJsonToConfig(data);
- }
-
- void LoadSave::saveWorkOffline(bool work_offline) {
- json data = getConfigJson();
- data["work_offline"] = work_offline;
- saveJsonToConfig(data);
- }
-
- void LoadSave::saveLoadedSkin(const std::string& name) {
- json data = getConfigJson();
- data["loaded_skin"] = name;
- saveJsonToConfig(data);
- }
-
- void LoadSave::saveAnimateWidgets(bool animate_widgets) {
- json data = getConfigJson();
- data["animate_widgets"] = animate_widgets;
- saveJsonToConfig(data);
- }
-
- void LoadSave::saveDisplayHzFrequency(bool hz_frequency) {
- json data = getConfigJson();
- data["hz_frequency"] = hz_frequency;
- saveJsonToConfig(data);
- }
-
- void LoadSave::saveAuthenticated(bool authenticated) {
- json data = getConfigJson();
- data["authenticated"] = authenticated;
- saveJsonToConfig(data);
- }
-
- void LoadSave::saveWindowSize(float window_size) {
- json data = getConfigJson();
- data["window_size"] = window_size;
- saveJsonToConfig(data);
- }
-
- void LoadSave::saveLayoutConfig(vital::StringLayout* layout) {
- std::wstring chromatic_layout;
- wchar_t up_key;
- wchar_t down_key;
-
- if (layout) {
- chromatic_layout = layout->getLayout();
- up_key = layout->getUpKey();
- down_key = layout->getDownKey();
- }
- else {
- chromatic_layout = getComputerKeyboardLayout();
- std::pair<wchar_t, wchar_t> octave_controls = getComputerKeyboardOctaveControls();
- down_key = octave_controls.first;
- up_key = octave_controls.second;
- }
-
- json layout_data;
-
- layout_data["chromatic_layout"] = chromatic_layout;
- layout_data["octave_up"] = up_key;
- layout_data["octave_down"] = down_key;
-
- json data = getConfigJson();
- data["keyboard_layout"] = layout_data;
- saveJsonToConfig(data);
- }
-
- void LoadSave::saveMidiMapConfig(MidiManager* midi_manager) {
- MidiManager::midi_map midi_learn_map = midi_manager->getMidiLearnMap();
-
- json midi_mapping_data;
-
- for (auto& midi_mapping : midi_learn_map) {
- json midi_map_data;
- midi_map_data["source"] = midi_mapping.first;
-
- json destinations_data;
- for (auto& midi_destination : midi_mapping.second) {
- json destination_data;
-
- destination_data["destination"] = midi_destination.first;
- destination_data["min_range"] = midi_destination.second->min;
- destination_data["max_range"] = midi_destination.second->max;
- destinations_data.push_back(destination_data);
- }
-
- midi_map_data["destinations"] = destinations_data;
- midi_mapping_data.push_back(midi_map_data);
- }
-
- json data = getConfigJson();
- data["midi_learn"] = midi_mapping_data;
- saveJsonToConfig(data);
- }
-
- void LoadSave::loadConfig(MidiManager* midi_manager, vital::StringLayout* layout) {
- json data = getConfigJson();
-
- // Computer Keyboard Layout
- if (layout) {
- layout->setLayout(getComputerKeyboardLayout());
- std::pair<wchar_t, wchar_t> octave_controls = getComputerKeyboardOctaveControls();
- layout->setDownKey(octave_controls.first);
- layout->setUpKey(octave_controls.second);
- }
-
- // Midi Learn Map
- if (data.count("midi_learn")) {
- MidiManager::midi_map midi_learn_map = midi_manager->getMidiLearnMap();
-
- json midi_mapping_data = data["midi_learn"];
- for (json& midi_map_data : midi_mapping_data) {
- int source = midi_map_data["source"];
-
- if (midi_map_data.count("destinations")) {
- json destinations_data = midi_map_data["destinations"];
- for (json& midi_destination : destinations_data) {
- std::string dest = midi_destination["destination"];
- midi_learn_map[source][dest] = &vital::Parameters::getDetails(dest);
- }
- }
- }
- midi_manager->setMidiLearnMap(midi_learn_map);
- }
- }
-
- bool LoadSave::hasDataDirectory() {
- json data = getConfigJson();
- if (data.count("data_directory")) {
- std::string path = data["data_directory"];
- File directory(path);
- File packages = directory.getChildFile(kInstalledPacksFile);
- return directory.exists() && directory.isDirectory() && packages.exists();
- }
- return false;
- }
-
- File LoadSave::getAvailablePacksFile() {
- json data = getConfigJson();
- if (data.count("data_directory") == 0)
- return File();
-
- std::string path = data["data_directory"];
- File directory(path);
- if (!directory.exists() || !directory.isDirectory())
- return File();
-
- return directory.getChildFile(kAvailablePacksFile);
- }
-
- json LoadSave::getAvailablePacks() {
- File packs_file = getAvailablePacksFile();
- if (!packs_file.exists())
- return json();
-
- try {
- json parsed = json::parse(packs_file.loadFileAsString().toStdString(), nullptr, false);
- if (parsed.is_discarded())
- return json();
- return parsed;
- }
- catch (const json::exception& e) {
- return json();
- }
- }
-
- File LoadSave::getInstalledPacksFile() {
- json data = getConfigJson();
- if (data.count("data_directory") == 0)
- return File();
-
- std::string path = data["data_directory"];
- File directory(path);
- if (!directory.exists() || !directory.isDirectory())
- return File();
-
- return directory.getChildFile(kInstalledPacksFile);
- }
-
- json LoadSave::getInstalledPacks() {
- File packs_file = getInstalledPacksFile();
- if (!packs_file.exists())
- return json();
-
- try {
- json parsed = json::parse(packs_file.loadFileAsString().toStdString(), nullptr, false);
- if (parsed.is_discarded())
- return json();
- return parsed;
- }
- catch (const json::exception& e) {
- return json();
- }
- }
-
- void LoadSave::saveInstalledPacks(const json& packs) {
- File packs_file = getInstalledPacksFile();
-
- if (!packs_file.exists())
- packs_file.create();
- packs_file.replaceWithText(packs.dump());
- }
-
- void LoadSave::markPackInstalled(int id) {
- json packs = getInstalledPacks();
- packs[std::to_string(id)] = 1;
- saveInstalledPacks(packs);
- }
-
- void LoadSave::markPackInstalled(const std::string& name) {
- json packs = getInstalledPacks();
- std::string cleaned = String(name).removeCharacters(" ._").toLowerCase().toStdString();
-
- packs[cleaned] = 1;
- saveInstalledPacks(packs);
- }
-
- void LoadSave::saveDataDirectory(const File& data_directory) {
- json data = getConfigJson();
- std::string path = data_directory.getFullPathName().toStdString();
- data["data_directory"] = path;
- saveJsonToConfig(data);
- }
-
- bool LoadSave::isInstalled() {
- return getDataDirectory().exists();
- }
-
- bool LoadSave::wasUpgraded() {
- json data = getConfigJson();
-
- if (!data.count("synth_version"))
- return true;
-
- std::string version = data["synth_version"];
- return compareVersionStrings(version, ProjectInfo::versionString) < 0;
- }
-
- bool LoadSave::isExpired() {
- return getDaysToExpire() < 0;
- }
-
- bool LoadSave::doesExpire() {
- #ifdef EXPIRE_DAYS
- return true;
- #else
- return false;
- #endif
- }
-
- int LoadSave::getDaysToExpire() {
- #ifdef EXPIRE_DAYS
- Time current_time = Time::getCurrentTime();
- Time build_time = getBuildTime();
-
- RelativeTime time_since_compile = current_time - build_time;
- int days_since_compile = time_since_compile.inDays();
- return EXPIRE_DAYS - days_since_compile;
- #else
- return 0;
- #endif
- }
-
- bool LoadSave::shouldCheckForUpdates() {
- json data = getConfigJson();
-
- if (!data.count("check_for_updates"))
- return true;
-
- return data["check_for_updates"];
- }
-
- bool LoadSave::shouldWorkOffline() {
- json data = getConfigJson();
-
- if (!data.count("work_offline"))
- return false;
-
- return data["work_offline"];
- }
-
- std::string LoadSave::getLoadedSkin() {
- json data = getConfigJson();
-
- if (!data.count("loaded_skin"))
- return "";
-
- return data["loaded_skin"];
- }
-
- bool LoadSave::shouldAnimateWidgets() {
- json data = getConfigJson();
-
- if (!data.count("animate_widgets"))
- return true;
-
- return data["animate_widgets"];
- }
-
- bool LoadSave::displayHzFrequency() {
- json data = getConfigJson();
-
- if (!data.count("hz_frequency"))
- return false;
-
- return data["hz_frequency"];
- }
-
- bool LoadSave::authenticated() {
- json data = getConfigJson();
-
- if (!data.count("authenticated"))
- return false;
-
- return data["authenticated"];
- }
-
- int LoadSave::getOversamplingAmount() {
- json data = getConfigJson();
-
- if (!data.count("oversampling_amount"))
- return 2;
-
- return data["oversampling_amount"];
- }
-
- float LoadSave::loadWindowSize() {
- static constexpr float kMinWindowSize = 0.25f;
-
- json data = getConfigJson();
-
- if (!data.count("window_size"))
- return 1.0f;
-
- return std::max<float>(kMinWindowSize, data["window_size"]);
- }
-
- String LoadSave::loadVersion() {
- json data = getConfigJson();
-
- if (!data.count("synth_version"))
- return "0.0.0";
-
- std::string version = data["synth_version"];
- return version;
- }
-
- String LoadSave::loadContentVersion() {
- json data = getConfigJson();
-
- if (!data.count("content_version"))
- return "0.0";
-
- std::string version = data["content_version"];
- return version;
- }
-
- std::wstring LoadSave::getComputerKeyboardLayout() {
- json data = getConfigJson();
-
- if (data.count("keyboard_layout")) {
- json layout = data["keyboard_layout"];
-
- if (layout.count("chromatic_layout"))
- return layout["chromatic_layout"];
- }
-
- return vital::kDefaultKeyboard;
- }
-
- std::string LoadSave::getPreferredTTWTLanguage() {
- json data = getConfigJson();
-
- if (!data.count("ttwt_language"))
- return "";
-
- std::string language = data["ttwt_language"];
- return language;
- }
-
- std::string LoadSave::getAuthor() {
- json data = getConfigJson();
-
- if (data.count("author"))
- return data["author"];
-
- return "";
- }
-
- std::pair<wchar_t, wchar_t> LoadSave::getComputerKeyboardOctaveControls() {
- std::pair<wchar_t, wchar_t> octave_controls(vital::kDefaultKeyboardOctaveDown, vital::kDefaultKeyboardOctaveUp);
- json data = getConfigJson();
-
- if (data.count("keyboard_layout")) {
- json layout = data["keyboard_layout"];
- std::wstring down = layout["octave_down"];
- std::wstring up = layout["octave_up"];
- octave_controls.first = down[0];
- octave_controls.second = up[0];
- }
-
- return octave_controls;
- }
-
- void LoadSave::saveAdditionalFolders(const std::string& name, std::vector<std::string> folders) {
- json data = getConfigJson();
- json wavetable_folders;
- for (std::string& folder : folders)
- wavetable_folders.push_back(folder);
- data[name] = wavetable_folders;
-
- saveJsonToConfig(data);
- }
-
- std::vector<std::string> LoadSave::getAdditionalFolders(const std::string& name) {
- json data = getConfigJson();
- std::vector<std::string> folders;
-
- if (data.count(name)) {
- json folder_list = data[name];
- for (json& folder : folder_list)
- folders.push_back(folder);
- }
-
- return folders;
- }
-
- File LoadSave::getDataDirectory() {
- json data = getConfigJson();
- if (data.count("data_directory")) {
- std::string path = data["data_directory"];
- File folder(path);
- if (folder.exists() && folder.isDirectory())
- return folder;
- }
-
- #ifdef LINUX
- File directory = File(kLinuxUserDataDirectory);
- String xdg_data_home = SystemStats::getEnvironmentVariable ("XDG_DATA_HOME", {});
-
- if (!xdg_data_home.trim().isEmpty())
- directory = File(xdg_data_home).getChildFile("vial");
-
- #elif defined(__APPLE__)
- File home_directory = File::getSpecialLocation(File::userHomeDirectory);
- File directory = home_directory.getChildFile("Music").getChildFile("Vial");
- #else
- File documents_dir = File::getSpecialLocation(File::userDocumentsDirectory);
- File directory = documents_dir.getChildFile("Vial");
- #endif
-
- return directory;
- }
-
- std::vector<File> LoadSave::getDirectories(const String& folder_name) {
- File data_dir = getDataDirectory();
- std::vector<File> directories;
-
- if (!data_dir.exists() || !data_dir.isDirectory())
- return directories;
-
- Array<File> sub_folders;
- sub_folders.add(data_dir);
- data_dir.findChildFiles(sub_folders, File::findDirectories, false);
- for (const File& sub_folder : sub_folders) {
- File directory = sub_folder.getChildFile(folder_name);
- if (directory.exists() && directory.isDirectory())
- directories.push_back(directory);
- }
-
- return directories;
- }
-
- std::vector<File> LoadSave::getPresetDirectories() {
- return getDirectories(kPresetFolderName);
- }
-
- std::vector<File> LoadSave::getWavetableDirectories() {
- return getDirectories(kWavetableFolderName);
- }
-
- std::vector<File> LoadSave::getSkinDirectories() {
- return getDirectories(kSkinFolderName);
- }
-
- std::vector<File> LoadSave::getSampleDirectories() {
- return getDirectories(kSampleFolderName);
- }
-
- std::vector<File> LoadSave::getLfoDirectories() {
- return getDirectories(kLfoFolderName);
- }
-
- File LoadSave::getUserDirectory() {
- File directory = getDataDirectory().getChildFile(kUserDirectoryName);
- if (!directory.exists())
- directory.createDirectory();
- return directory;
- }
-
- File LoadSave::getUserPresetDirectory() {
- File directory = getUserDirectory().getChildFile(kPresetFolderName);
- if (!directory.exists())
- directory.createDirectory();
- return directory;
- }
-
- File LoadSave::getUserWavetableDirectory() {
- File directory = getUserDirectory().getChildFile(kWavetableFolderName);
- if (!directory.exists())
- directory.createDirectory();
- return directory;
- }
-
- File LoadSave::getUserSkinDirectory() {
- File directory = getUserDirectory().getChildFile(kSkinFolderName);
- if (!directory.exists())
- directory.createDirectory();
- return directory;
- }
-
- File LoadSave::getUserSampleDirectory() {
- File directory = getUserDirectory().getChildFile(kSampleFolderName);
- if (!directory.exists())
- directory.createDirectory();
- return directory;
- }
-
- File LoadSave::getUserLfoDirectory() {
- File directory = getUserDirectory().getChildFile(kLfoFolderName);
- if (!directory.exists())
- directory.createDirectory();
- return directory;
- }
-
- void LoadSave::getAllFilesOfTypeInDirectories(Array<File>& files, const String& extensions,
- const std::vector<File>& directories) {
- files.clear();
- for (const File& directory : directories) {
- if (directory.exists() && directory.isDirectory())
- directory.findChildFiles(files, File::findFiles, true, extensions);
- }
- }
-
- void LoadSave::getAllPresets(Array<File>& presets) {
- getAllFilesOfTypeInDirectories(presets, String("*.") + vital::kPresetExtension, getPresetDirectories());
- }
-
- void LoadSave::getAllWavetables(Array<File>& wavetables) {
- getAllFilesOfTypeInDirectories(wavetables, vital::kWavetableExtensionsList, getWavetableDirectories());
- }
-
- void LoadSave::getAllSkins(Array<File>& skins) {
- getAllFilesOfTypeInDirectories(skins, String("*.") + vital::kSkinExtension, getSkinDirectories());
- }
-
- void LoadSave::getAllLfos(Array<File>& lfos) {
- getAllFilesOfTypeInDirectories(lfos, String("*.") + vital::kLfoExtension, getLfoDirectories());
- }
-
- void LoadSave::getAllSamples(Array<File>& samples) {
- getAllFilesOfTypeInDirectories(samples, "*.wav", getSampleDirectories());
- }
-
- void LoadSave::getAllUserPresets(Array<File>& presets) {
- std::vector<File> directories = {
- getDataDirectory().getChildFile(kPresetFolderName),
- getUserPresetDirectory()
- };
- getAllFilesOfTypeInDirectories(presets, String("*.") + vital::kPresetExtension, directories);
- }
-
- void LoadSave::getAllUserWavetables(Array<File>& wavetables) {
- std::vector<File> directories = {
- getDataDirectory().getChildFile(kWavetableFolderName),
- getUserWavetableDirectory()
- };
- getAllFilesOfTypeInDirectories(wavetables, vital::kWavetableExtensionsList, directories);
- }
-
- void LoadSave::getAllUserLfos(Array<File>& lfos) {
- std::vector<File> directories = {
- getDataDirectory().getChildFile(kLfoFolderName),
- getUserLfoDirectory()
- };
- getAllFilesOfTypeInDirectories(lfos, String("*.") + vital::kLfoExtension, directories);
- }
-
- void LoadSave::getAllUserSamples(Array<File>& samples) {
- std::vector<File> directories = {
- getDataDirectory().getChildFile(kSampleFolderName),
- getUserSampleDirectory()
- };
- getAllFilesOfTypeInDirectories(samples, "*.wav", directories);
- }
-
- int LoadSave::compareFeatureVersionStrings(String a, String b) {
- a.trim();
- b.trim();
-
- return compareVersionStrings(a.upToLastOccurrenceOf(".", false, true),
- b.upToLastOccurrenceOf(".", false, true));
- }
-
- int LoadSave::compareVersionStrings(String a, String b) {
- a.trim();
- b.trim();
-
- if (a.isEmpty() && b.isEmpty())
- return 0;
-
- String major_version_a = a.upToFirstOccurrenceOf(".", false, true);
- String major_version_b = b.upToFirstOccurrenceOf(".", false, true);
-
- if (!major_version_a.containsOnly("0123456789"))
- major_version_a = "0";
- if (!major_version_b.containsOnly("0123456789"))
- major_version_b = "0";
-
- int major_value_a = major_version_a.getIntValue();
- int major_value_b = major_version_b.getIntValue();
-
- if (major_value_a > major_value_b)
- return 1;
- else if (major_value_a < major_value_b)
- return -1;
- return compareVersionStrings(a.fromFirstOccurrenceOf(".", false, true),
- b.fromFirstOccurrenceOf(".", false, true));
- }
-
- File LoadSave::getShiftedFile(const String directory_name, const String& extensions,
- const std::string& additional_folders_name, const File& current_file, int shift) {
- FileSorterAscending file_sorter;
-
- std::vector<File> directories = getDirectories(directory_name);
- std::vector<std::string> additional = getAdditionalFolders(additional_folders_name);
- for (const std::string& path : additional)
- directories.push_back(File(path));
-
- Array<File> all_files;
- getAllFilesOfTypeInDirectories(all_files, extensions, directories);
- if (all_files.isEmpty())
- return File();
-
- all_files.sort(file_sorter);
- int index = all_files.indexOf(current_file);
- if (index < 0)
- return all_files[0];
- return all_files[(index + shift + all_files.size()) % all_files.size()];
- }
|