| @@ -19,9 +19,10 @@ | |||||
| #include <vector> | #include <vector> | ||||
| #include <memory> | #include <memory> | ||||
| #include <set> | |||||
| #include "../JuceLibraryCode/JuceHeader.h" | #include "../JuceLibraryCode/JuceHeader.h" | ||||
| const String g_plugintitle{ "PaulXStretch 1.3.0" }; | |||||
| const String g_plugintitle{ "PaulXStretch 1.2.4" }; | |||||
| using REALTYPE = float; | using REALTYPE = float; | ||||
| @@ -115,10 +116,13 @@ inline void storeToTreeProperties(ValueTree dest, UndoManager* uman, AudioParame | |||||
| if (par) dest.setProperty(par->paramID,(int)*par,uman); | if (par) dest.setProperty(par->paramID,(int)*par,uman); | ||||
| } | } | ||||
| inline void storeToTreeProperties(ValueTree dest, UndoManager* uman, const OwnedArray<AudioProcessorParameter>& pars) | |||||
| inline void storeToTreeProperties(ValueTree dest, UndoManager* uman, const OwnedArray<AudioProcessorParameter>& pars, | |||||
| const std::set<AudioProcessorParameter*>& ignorepars = {}) | |||||
| { | { | ||||
| for (auto& e : pars) | for (auto& e : pars) | ||||
| { | { | ||||
| if (ignorepars.count(e)) | |||||
| continue; | |||||
| auto parf = dynamic_cast<AudioParameterFloat*>(e); | auto parf = dynamic_cast<AudioParameterFloat*>(e); | ||||
| if (parf != nullptr) | if (parf != nullptr) | ||||
| storeToTreeProperties(dest, nullptr, parf); | storeToTreeProperties(dest, nullptr, parf); | ||||
| @@ -124,8 +124,6 @@ PaulstretchpluginAudioProcessorEditor::PaulstretchpluginAudioProcessorEditor(Pau | |||||
| { | { | ||||
| m_parcomps.emplace_back(std::make_unique<ParameterComponent>(pars[i], notifyonlyonrelease)); | m_parcomps.emplace_back(std::make_unique<ParameterComponent>(pars[i], notifyonlyonrelease)); | ||||
| m_parcomps.back()->m_group_id = group_id; | m_parcomps.back()->m_group_id = group_id; | ||||
| if (i == cpi_capture_trigger) | |||||
| m_parcomps.back()->m_nonparamstate = &processor.m_is_recording; | |||||
| if (group_id >= -1) | if (group_id >= -1) | ||||
| addAndMakeVisible(m_parcomps.back().get()); | addAndMakeVisible(m_parcomps.back().get()); | ||||
| } | } | ||||
| @@ -1255,20 +1253,10 @@ void ParameterComponent::sliderDragEnded(Slider * slid) | |||||
| void ParameterComponent::buttonClicked(Button * but) | void ParameterComponent::buttonClicked(Button * but) | ||||
| { | { | ||||
| AudioParameterBool* boolpar = dynamic_cast<AudioParameterBool*>(m_par); | AudioParameterBool* boolpar = dynamic_cast<AudioParameterBool*>(m_par); | ||||
| if (m_togglebut != nullptr) // && m_togglebut->getToggleState() != *boolpar) | |||||
| if (m_togglebut != nullptr) | |||||
| { | { | ||||
| if (m_nonparamstate == nullptr) | |||||
| { | |||||
| if (m_togglebut->getToggleState()!=*boolpar) | |||||
| *boolpar = m_togglebut->getToggleState(); | |||||
| } | |||||
| else | |||||
| { | |||||
| // If we have the non-parameter state pointer, just set the target parameter to true. | |||||
| // Logic in the AudioProcessor determines what should be done and it sets the parameter immediately back | |||||
| // to false when it sees the parameter is true. | |||||
| *boolpar = true; | |||||
| } | |||||
| if (m_togglebut->getToggleState()!=*boolpar) | |||||
| *boolpar = m_togglebut->getToggleState(); | |||||
| } | } | ||||
| } | } | ||||
| @@ -1285,19 +1273,10 @@ void ParameterComponent::updateComponent() | |||||
| m_slider->setValue(*intpar, dontSendNotification); | m_slider->setValue(*intpar, dontSendNotification); | ||||
| } | } | ||||
| AudioParameterBool* boolpar = dynamic_cast<AudioParameterBool*>(m_par); | AudioParameterBool* boolpar = dynamic_cast<AudioParameterBool*>(m_par); | ||||
| if (m_togglebut != nullptr) | |||||
| if (boolpar!=nullptr && m_togglebut != nullptr) | |||||
| { | { | ||||
| if (m_nonparamstate == nullptr) | |||||
| { | |||||
| if (m_togglebut->getToggleState() != *boolpar) | |||||
| m_togglebut->setToggleState(*boolpar, dontSendNotification); | |||||
| } | |||||
| else | |||||
| { | |||||
| // If we have the non-parameter state pointer, get the button toggle state from that | |||||
| if (m_togglebut->getToggleState()!=*m_nonparamstate) | |||||
| m_togglebut->setToggleState(*m_nonparamstate, dontSendNotification); | |||||
| } | |||||
| if (m_togglebut->getToggleState() != *boolpar) | |||||
| m_togglebut->setToggleState(*boolpar, dontSendNotification); | |||||
| } | } | ||||
| } | } | ||||
| @@ -91,7 +91,7 @@ public: | |||||
| void setHighLighted(bool b); | void setHighLighted(bool b); | ||||
| int m_group_id = -1; | int m_group_id = -1; | ||||
| Slider* getSlider() { return m_slider.get(); } | Slider* getSlider() { return m_slider.get(); } | ||||
| bool* m_nonparamstate = nullptr; | |||||
| private: | private: | ||||
| Label m_label; | Label m_label; | ||||
| AudioProcessorParameter* m_par = nullptr; | AudioProcessorParameter* m_par = nullptr; | ||||
| @@ -259,7 +259,7 @@ int PaulstretchpluginAudioProcessor::getPreBufferAmount() | |||||
| ValueTree PaulstretchpluginAudioProcessor::getStateTree(bool ignoreoptions, bool ignorefile) | ValueTree PaulstretchpluginAudioProcessor::getStateTree(bool ignoreoptions, bool ignorefile) | ||||
| { | { | ||||
| ValueTree paramtree("paulstretch3pluginstate"); | ValueTree paramtree("paulstretch3pluginstate"); | ||||
| storeToTreeProperties(paramtree, nullptr, getParameters()); | |||||
| storeToTreeProperties(paramtree, nullptr, getParameters(), { getBoolParameter(cpi_capture_trigger) }); | |||||
| if (m_current_file != File() && ignorefile == false) | if (m_current_file != File() && ignorefile == false) | ||||
| { | { | ||||
| paramtree.setProperty("importedfile", m_current_file.getFullPathName(), nullptr); | paramtree.setProperty("importedfile", m_current_file.getFullPathName(), nullptr); | ||||
| @@ -1014,13 +1014,11 @@ void PaulstretchpluginAudioProcessor::timerCallback(int id) | |||||
| if (capture == true && m_is_recording == false) | if (capture == true && m_is_recording == false) | ||||
| { | { | ||||
| setRecordingEnabled(true); | setRecordingEnabled(true); | ||||
| *getBoolParameter(cpi_capture_trigger)=false; | |||||
| return; | return; | ||||
| } | } | ||||
| if (capture == true && m_is_recording == true) | |||||
| if (capture == false && m_is_recording == true) | |||||
| { | { | ||||
| setRecordingEnabled(false); | setRecordingEnabled(false); | ||||
| *getBoolParameter(cpi_capture_trigger) = false; | |||||
| return; | return; | ||||
| } | } | ||||
| if (m_cur_num_out_chans != *m_outchansparam) | if (m_cur_num_out_chans != *m_outchansparam) | ||||
| @@ -237,7 +237,7 @@ public: | |||||
| void* ptr, | void* ptr, | ||||
| float opt) override; | float opt) override; | ||||
| int m_cur_tab_index = 0; | int m_cur_tab_index = 0; | ||||
| bool m_is_recording = false; | |||||
| bool m_save_captured_audio = true; | bool m_save_captured_audio = true; | ||||
| String m_capture_location; | String m_capture_location; | ||||
| bool m_midinote_control = false; | bool m_midinote_control = false; | ||||
| @@ -255,7 +255,7 @@ private: | |||||
| CriticalSection m_cs; | CriticalSection m_cs; | ||||
| File m_current_file; | File m_current_file; | ||||
| Time m_current_file_date; | Time m_current_file_date; | ||||
| bool m_is_recording = false; | |||||
| TimeSliceThread m_bufferingthread; | TimeSliceThread m_bufferingthread; | ||||
| std::unique_ptr<StretchAudioSource> m_stretch_source; | std::unique_ptr<StretchAudioSource> m_stretch_source; | ||||
| std::unique_ptr<MyBufferingAudioSource> m_buffering_source; | std::unique_ptr<MyBufferingAudioSource> m_buffering_source; | ||||
| @@ -7,9 +7,11 @@ Copyright (C) 2017-2018 Xenakios | |||||
| Released under GNU General Public License v.3 license. | Released under GNU General Public License v.3 license. | ||||
| History : | History : | ||||
| 01-21-2019 1.3.0 | |||||
| -Changed Import file button to show/hide a file browser for audio files. (This seems to be the only | |||||
| 02-12-2019 1.2.4 | |||||
| -Changed Import file button to show/hide an overlaid file browser for audio files. (This seems to be the only | |||||
| technically correct way to browse for the files.) | technically correct way to browse for the files.) | ||||
| -Fix the fix for the Capture parameter. (Recalling it when undoing and loading project should now be ignored, | |||||
| while still allowing automation and MIDI learn.) | |||||
| 01-17-2019 1.2.3 | 01-17-2019 1.2.3 | ||||
| -Captured audio buffers can optionally be saved as files on disk for later recall. | -Captured audio buffers can optionally be saved as files on disk for later recall. | ||||
| -Added varispeed (resampling speed change) feature when spectral stretch engine is bypassed | -Added varispeed (resampling speed change) feature when spectral stretch engine is bypassed | ||||