diff --git a/Source/FilePicker.cpp b/Source/FilePicker.cpp index 4787f49..d2a7eff 100644 --- a/Source/FilePicker.cpp +++ b/Source/FilePicker.cpp @@ -66,7 +66,8 @@ void FilePicker::valueTreePropertyChanged(ValueTree& treeWhosePropertyHasChanged // if (&treeWhosePropertyHasChanged == &valueTree) { if (property == StringRef("path")) { String soundFontPath{treeWhosePropertyHasChanged.getProperty("path", "")}; - // DEBUG_PRINT(soundFontPath); + DEBUG_PRINT(soundFontPath); + setDisplayedFilePath(soundFontPath); // if (soundFontPath.isNotEmpty()) { // loadFont(soundFontPath); // } @@ -75,9 +76,9 @@ void FilePicker::valueTreePropertyChanged(ValueTree& treeWhosePropertyHasChanged } void FilePicker::setDisplayedFilePath(const String& path) { - // if (!shouldChangeDisplayedFilePath(path)) { - // return; - // } + if (!shouldChangeDisplayedFilePath(path)) { + return; + } // currentPath = path; fileChooser.setCurrentFile(File(path), true, dontSendNotification); } diff --git a/Source/FilePicker.h b/Source/FilePicker.h index f590604..5d34c8c 100644 --- a/Source/FilePicker.h +++ b/Source/FilePicker.h @@ -50,4 +50,4 @@ private: bool shouldChangeDisplayedFilePath(const String &path); JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FilePicker) -}; \ No newline at end of file +}; diff --git a/Source/FluidSynthModel.cpp b/Source/FluidSynthModel.cpp index d0294c0..20fd318 100644 --- a/Source/FluidSynthModel.cpp +++ b/Source/FluidSynthModel.cpp @@ -20,10 +20,10 @@ FluidSynthModel::FluidSynthModel( // , sharedParams{sharedParams} //, synth{nullptr} , settings{nullptr, nullptr} -, currentSoundFontAbsPath{} +//, currentSoundFontAbsPath{} , currentSampleRate{44100} -, initialised{false} -, sfont_id{0} +//, initialised{false} +, sfont_id{-1} , channel{0}/*, mod(nullptr)*/ { @@ -97,12 +97,15 @@ void FluidSynthModel::initialise() { // loadFont(sharedParams.getSoundFontPath()); // changePreset(sharedParams->getBank(), sharedParams->getPreset()); // } + ValueTree soundFont{valueTreeState.state.getChildWithName("soundFont")}; + String path{soundFont.getProperty("path", "")}; + loadFont(path); fluid_synth_set_gain(synth.get(), 2.0); - for(int i{SOUND_CTRL1}; i <= SOUND_CTRL10; i++) - { - setControllerValue(i, 0); + fluid_midi_control_change controllers[]{SOUND_CTRL2, SOUND_CTRL3, SOUND_CTRL4, SOUND_CTRL5, SOUND_CTRL6, SOUND_CTRL10}; + for(fluid_midi_control_change controller : controllers) { + setControllerValue(static_cast(controller), 0); } // fluid_synth_bank_select(synth, 0, 3); @@ -116,7 +119,7 @@ void FluidSynthModel::initialise() { // float env_amount(12000.0f); // http://www.synthfont.com/SoundFont_NRPNs.PDF - float env_amount(20000.0f); + float env_amount{20000.0f}; // float env_amount(24000.0f); // note: fluid_chan.c#fluid_channel_init_ctrl() @@ -200,7 +203,7 @@ void FluidSynthModel::initialise() { fluid_mod_set_amount(mod.get(), 1000.0f); fluid_synth_add_default_mod(synth.get(), mod.get(), FLUID_SYNTH_ADD); - valueTreeState.state.getChildWithName("soundFont").sendPropertyChangeMessage("path"); +// valueTreeState.state.getChildWithName("soundFont").sendPropertyChangeMessage("path"); // valueTree.sendPropertyChangeMessage("soundFontPath"); // initialised = true; @@ -273,7 +276,7 @@ void FluidSynthModel::valueTreePropertyChanged(ValueTree& treeWhosePropertyHasCh if (property == StringRef("path")) { String soundFontPath{treeWhosePropertyHasChanged.getProperty("path", "")}; if (soundFontPath.isNotEmpty()) { - loadFont(soundFontPath); + unloadAndLoadFont(soundFontPath); } } } @@ -294,82 +297,82 @@ int FluidSynthModel::getChannel() { return channel; } -void FluidSynthModel::changePreset(int bank, int preset) { - if (bank == -1 || preset == -1) { - unique_ptr bankAndPreset = getFirstBankAndPreset(); - bank = bankAndPreset->getBank(); - preset = bankAndPreset->getPreset(); - } - changePresetImpl(bank, preset); -// sharedParams->setPreset(preset); -// sharedParams->setBank(bank); -} +//void FluidSynthModel::changePreset(int bank, int preset) { +// if (bank == -1 || preset == -1) { +// unique_ptr bankAndPreset = getFirstBankAndPreset(); +// bank = bankAndPreset->getBank(); +// preset = bankAndPreset->getPreset(); +// } +// changePresetImpl(bank, preset); +//// sharedParams->setPreset(preset); +//// sharedParams->setBank(bank); +//} -void FluidSynthModel::changePresetImpl(int bank, int preset) { - fluid_synth_program_select(synth.get(), channel, sfont_id, static_cast(bank), static_cast(preset)); -} +//void FluidSynthModel::changePresetImpl(int bank, int preset) { +// fluid_synth_program_select(synth.get(), channel, sfont_id, static_cast(bank), static_cast(preset)); +//} -fluid_preset_t* FluidSynthModel::getFirstPreset() { - fluid_sfont_t* sfont = fluid_synth_get_sfont_by_id(synth.get(), sfont_id); +//fluid_preset_t* FluidSynthModel::getFirstPreset() { +// fluid_sfont_t* sfont = fluid_synth_get_sfont_by_id(synth.get(), sfont_id); +// +// jassert(sfont != nullptr); +// fluid_sfont_iteration_start(sfont); +// +// return fluid_sfont_iteration_next(sfont); +//} +// +//unique_ptr FluidSynthModel::getFirstBankAndPreset() { +// fluid_preset_t* preset = getFirstPreset(); +// +// int offset = fluid_synth_get_bank_offset(synth.get(), sfont_id); +// +// return make_unique(fluid_preset_get_banknum(preset) + offset, fluid_preset_get_num(preset)); +//}; +// +//void FluidSynthModel::selectFirstPreset() { +// fluid_preset_t* preset = getFirstPreset(); +// +// int offset = fluid_synth_get_bank_offset(synth.get(), sfont_id); +// +// changePreset(fluid_preset_get_banknum(preset) + offset, fluid_preset_get_num(preset)); +//} - jassert(sfont != nullptr); - fluid_sfont_iteration_start(sfont); - - return fluid_sfont_iteration_next(sfont); -} - -unique_ptr FluidSynthModel::getFirstBankAndPreset() { - fluid_preset_t* preset = getFirstPreset(); - - int offset = fluid_synth_get_bank_offset(synth.get(), sfont_id); - - return make_unique(fluid_preset_get_banknum(preset) + offset, fluid_preset_get_num(preset)); -}; - -void FluidSynthModel::selectFirstPreset() { - fluid_preset_t* preset = getFirstPreset(); - - int offset = fluid_synth_get_bank_offset(synth.get(), sfont_id); - - changePreset(fluid_preset_get_banknum(preset) + offset, fluid_preset_get_num(preset)); -} - -BanksToPresets FluidSynthModel::getBanks() { - BanksToPresets banksToPresets; - - int soundfontCount = fluid_synth_sfcount(synth.get()); - - if (soundfontCount == 0) { - // no soundfont selected - return banksToPresets; - } - - fluid_sfont_t* sfont = fluid_synth_get_sfont_by_id(synth.get(), sfont_id); - if(sfont == nullptr) { - // no soundfont found by that ID - // the above guard (soundfontCount) protects us for the - // main case we're expecting. this guard is just defensive programming. - return banksToPresets; - } - - int offset = fluid_synth_get_bank_offset(synth.get(), sfont_id); - - fluid_sfont_iteration_start(sfont); - - for(fluid_preset_t* preset = fluid_sfont_iteration_next(sfont); - preset != nullptr; - preset = fluid_sfont_iteration_next(sfont)) { - banksToPresets.insert(BanksToPresets::value_type( - fluid_preset_get_banknum(preset) + offset, - *new Preset( - fluid_preset_get_num(preset), - fluid_preset_get_name(preset) - ) - )); - } - - return banksToPresets; -} +//BanksToPresets FluidSynthModel::getBanks() { +// BanksToPresets banksToPresets; +// +// int soundfontCount = fluid_synth_sfcount(synth.get()); +// +// if (soundfontCount == 0) { +// // no soundfont selected +// return banksToPresets; +// } +// +// fluid_sfont_t* sfont = fluid_synth_get_sfont_by_id(synth.get(), sfont_id); +// if(sfont == nullptr) { +// // no soundfont found by that ID +// // the above guard (soundfontCount) protects us for the +// // main case we're expecting. this guard is just defensive programming. +// return banksToPresets; +// } +// +// int offset = fluid_synth_get_bank_offset(synth.get(), sfont_id); +// +// fluid_sfont_iteration_start(sfont); +// +// for(fluid_preset_t* preset = fluid_sfont_iteration_next(sfont); +// preset != nullptr; +// preset = fluid_sfont_iteration_next(sfont)) { +// banksToPresets.insert(BanksToPresets::value_type( +// fluid_preset_get_banknum(preset) + offset, +// *new Preset( +// fluid_preset_get_num(preset), +// fluid_preset_get_name(preset) +// ) +// )); +// } +// +// return banksToPresets; +//} shared_ptr FluidSynthModel::getSynth() { // https://msdn.microsoft.com/en-us/library/hh279669.aspx @@ -378,38 +381,50 @@ shared_ptr FluidSynthModel::getSynth() { return synth; } -void FluidSynthModel::onFileNameChanged(const String &absPath, int bank, int preset) { - if (!shouldLoadFont(absPath)) { - return; - } - unloadAndLoadFont(absPath); - changePreset(bank, preset); - ValueTree valueTree{valueTreeState.state.getChildWithName("soundFont")}; - valueTree.setPropertyExcludingListener(this, "path", absPath, nullptr); - // valueTree.setPropertyExcludingListener(this, "soundFontPath", absPath, nullptr); -// sharedParams.setSoundFontPath(absPath); - // eventListeners.call(&FluidSynthModel::Listener::fontChanged, this, absPath); -} +//void FluidSynthModel::onFileNameChanged(const String &absPath, int bank, int preset) { +// if (!shouldLoadFont(absPath)) { +// return; +// } +// unloadAndLoadFont(absPath); +// changePreset(bank, preset); +// ValueTree valueTree{valueTreeState.state.getChildWithName("soundFont")}; +// valueTree.setPropertyExcludingListener(this, "path", absPath, nullptr); +// // valueTree.setPropertyExcludingListener(this, "soundFontPath", absPath, nullptr); +//// sharedParams.setSoundFontPath(absPath); +// // eventListeners.call(&FluidSynthModel::Listener::fontChanged, this, absPath); +//} void FluidSynthModel::unloadAndLoadFont(const String &absPath) { // in the base case, there is no font loaded if (fluid_synth_sfcount(synth.get()) > 0) { + // if -1 is returned, that indicates failure + // not really sure how to handle "fail to unload" fluid_synth_sfunload(synth.get(), sfont_id, 1); + sfont_id = -1; } loadFont(absPath); } void FluidSynthModel::loadFont(const String &absPath) { - currentSoundFontAbsPath = absPath; - sfont_id++; - fluid_synth_sfload(synth.get(), absPath.toStdString().c_str(), 1); +// currentSoundFontAbsPath = absPath; +// sfont_id++; +// fluid_synth_sfunload(synth.get(), sfont_id, 1); + if (!absPath.isEmpty()) { + sfont_id = fluid_synth_sfload(synth.get(), absPath.toStdString().c_str(), 1); + // if -1 is returned, that indicates failure + } + // refresh regardless of success, if only to clear the table refreshBanks(); } void FluidSynthModel::refreshBanks() { - fluid_sfont_t* sfont {fluid_synth_get_sfont_by_id(synth.get(), sfont_id)}; ValueTree banks{"banks"}; - if (sfont != nullptr) { + fluid_sfont_t* sfont{ + sfont_id == -1 + ? nullptr + : fluid_synth_get_sfont_by_id(synth.get(), sfont_id) + }; + if (sfont) { int greatestEncounteredBank{-1}; ValueTree bank; @@ -440,8 +455,8 @@ void FluidSynthModel::refreshBanks() { valueTreeState.state.getChildWithName("banks").sendPropertyChangeMessage("synthetic"); #if JUCE_DEBUG - unique_ptr xml{valueTreeState.state.createXml()}; - Logger::outputDebugString(xml->createDocument("",false,false)); +// unique_ptr xml{valueTreeState.state.createXml()}; +// Logger::outputDebugString(xml->createDocument("",false,false)); #endif } @@ -557,22 +572,22 @@ void FluidSynthModel::refreshBanks() { // FluidSynthModel::Listener::~Listener() { // } -bool FluidSynthModel::shouldLoadFont(const String &absPath) { - if (absPath.isEmpty()) { - return false; - } - if (absPath == currentSoundFontAbsPath) { - return false; - } - return true; -} +//bool FluidSynthModel::shouldLoadFont(const String &absPath) { +// if (absPath.isEmpty()) { +// return false; +// } +//// if (absPath == currentSoundFontAbsPath) { +//// return false; +//// } +// return true; +//} // void FluidSynthModel::Listener::fontChanged(FluidSynthModel * model, const String &absPath) { // } -const String& FluidSynthModel::getCurrentSoundFontAbsPath() { - return currentSoundFontAbsPath; -} +//const String& FluidSynthModel::getCurrentSoundFontAbsPath() { +// return currentSoundFontAbsPath; +//} //============================================================================== // void FluidSynthModel::addListener (FluidSynthModel::Listener* const newListener) diff --git a/Source/FluidSynthModel.h b/Source/FluidSynthModel.h index 92a06e6..3978721 100644 --- a/Source/FluidSynthModel.h +++ b/Source/FluidSynthModel.h @@ -31,12 +31,12 @@ public: shared_ptr getSynth(); void initialise(); - BanksToPresets getBanks(); +// BanksToPresets getBanks(); - void changePreset(int bank, int preset); +// void changePreset(int bank, int preset); int getChannel(); - void onFileNameChanged(const String &absPath, int bank, int preset); +// void onFileNameChanged(const String &absPath, int bank, int preset); void setControllerValue(int controller, int value); //============================================================================== @@ -68,7 +68,7 @@ public: void setSampleRate(float sampleRate); - const String& getCurrentSoundFontAbsPath(); +// const String& getCurrentSoundFontAbsPath(); virtual void parameterChanged (const String& parameterID, float newValue) override; @@ -123,7 +123,7 @@ private: shared_ptr synth; // unique_ptr midiDriver; - String currentSoundFontAbsPath; +// String currentSoundFontAbsPath; float currentSampleRate; @@ -133,12 +133,12 @@ private: void unloadAndLoadFont(const String &absPath); void loadFont(const String &absPath); - bool shouldLoadFont(const String &absPath); +// bool shouldLoadFont(const String &absPath); void changePresetImpl(int bank, int preset); - bool initialised; - unsigned int sfont_id; +// bool initialised; + int sfont_id; unsigned int channel; // fluid_mod_t* mod; diff --git a/Source/PluginProcessor.cpp b/Source/PluginProcessor.cpp index 2ad8085..e9831c5 100644 --- a/Source/PluginProcessor.cpp +++ b/Source/PluginProcessor.cpp @@ -218,7 +218,7 @@ void JuicySFAudioProcessor::processBlock (AudioBuffer& buffer, MidiBuffer int time; MidiMessage m; - // TODO: factor into a MidiCollector + // TODO: factor into a MidiMessageCollector for (MidiBuffer::Iterator i (midiMessages); i.getNextEvent (m, time);) { DEBUG_PRINT ( m.getDescription() ); @@ -385,10 +385,10 @@ void JuicySFAudioProcessor::getStateInformation (MemoryBlock& destData) // as intermediaries to make it easy to save and load complex data. // Create an outer XML element.. -// XmlElement xml{"MYPLUGINSETTINGS"}; + XmlElement xml{"MYPLUGINSETTINGS"}; // sharedParams->setAttributesOnXml(xml); - auto state{valueTreeState.copyState()}; - unique_ptr xml{state.createXml()}; +// auto state{valueTreeState.copyState()}; +// unique_ptr xml{state.createXml()}; // sharedParams.setAttributesOnXml(xml); // list::iterator p; @@ -397,14 +397,44 @@ void JuicySFAudioProcessor::getStateInformation (MemoryBlock& destData) // } // Store the values of all our parameters, using their param ID as the XML attribute - // for (auto* param : getParameters()) - // if (auto* p = dynamic_cast (param)) - // xml->setAttribute (p->paramID, p->getValue()); + XmlElement* params{xml.createNewChildElement("params")}; + for (auto* param : getParameters()) { + if (auto* p = dynamic_cast (param)) { +// xml.setAttribute(p->paramID, p->getValue()); +// XmlElement* param{params->createNewChildElement("PARAM")}; +// param->setAttribute(p->paramID, p->getValue()); + params->setAttribute(p->paramID, p->getValue()); + } + } + { + ValueTree tree{valueTreeState.state.getChildWithName("uiState")}; + XmlElement* newElement{xml.createNewChildElement("uiState")}; +// Value value{tree.getPropertyAsValue("width", nullptr)}; + { + double value{tree.getProperty("width", GuiConstants::minWidth)}; + newElement->setAttribute("width", value); + } + { + double value{tree.getProperty("height", GuiConstants::minHeight)}; + newElement->setAttribute("height", value); + } + } + { + ValueTree tree{valueTreeState.state.getChildWithName("soundFont")}; + XmlElement* newElement{xml.createNewChildElement("soundFont")}; + { + String value{tree.getProperty("path", "")}; + newElement->setAttribute("path", value); + } + } + + DEBUG_PRINT(xml.createDocument("",false,false)); // then use this helper function to stuff it into the binary blob and return it.. - if (xml.get() != nullptr) { - copyXmlToBinary(*xml, destData); - } +// if (xml.get() != nullptr) { +// copyXmlToBinary(*xml, destData); +// } + copyXmlToBinary(xml, destData); } void JuicySFAudioProcessor::setStateInformation (const void* data, int sizeInBytes) @@ -433,16 +463,24 @@ void JuicySFAudioProcessor::setStateInformation (const void* data, int sizeInByt // if (xmlState->hasTagName ("MYPLUGINSETTINGS")) { if (xmlState->hasTagName(valueTreeState.state.getType())) { // valueTreeState.replaceState(ValueTree::fromXml(*xmlState)); - for (auto* param : getParameters()) - if (auto* p = dynamic_cast(param)) - p->setValue(static_cast(xmlState->getDoubleAttribute(p->paramID, p->getValue()))); +// for (auto* param : getParameters()) +// if (auto* p = dynamic_cast(param)) +// p->setValue(static_cast(xmlState->getDoubleAttribute(p->paramID, p->getValue()))); + XmlElement* params{xmlState->getChildByName("params")}; + if (params) { + for (auto* param : getParameters()) + if (auto* p = dynamic_cast(param)) + // XmlElement* xmlParam{params->getChildByAttribute("id", p->paramID)}; + // p->setValue(static_cast(xmlState->getDoubleAttribute(p->paramID, p->getValue()))); + p->setValue(static_cast(params->getDoubleAttribute(p->paramID, p->getValue()))); + } { // Value value{valueTreeState.state.getPropertyAsValue("soundFontPath", nullptr)}; // value = xmlState->getStringAttribute("soundFontPath", value.getValue()); - ValueTree tree{valueTreeState.state.getChildWithName("soundFont")}; XmlElement* xmlElement{xmlState->getChildByName("soundFont")}; if (xmlElement) { + ValueTree tree{valueTreeState.state.getChildWithName("soundFont")}; Value value{tree.getPropertyAsValue("path", nullptr)}; value = xmlState->getStringAttribute("path", value.getValue()); }