diff --git a/source/backend/plugin/NativePlugin.cpp b/source/backend/plugin/NativePlugin.cpp index f93b22acc..04a25e219 100644 --- a/source/backend/plugin/NativePlugin.cpp +++ b/source/backend/plugin/NativePlugin.cpp @@ -32,7 +32,8 @@ void carla_register_native_plugin_midiThrough(); void carla_register_native_plugin_midiTranspose(); void carla_register_native_plugin_nekofilter(); void carla_register_native_plugin_sunvoxfile(); -void carla_register_native_plugin_vex(); +void carla_register_native_plugin_vex_fx(); +void carla_register_native_plugin_vex_synth(); #ifndef BUILD_BRIDGE // Carla @@ -65,7 +66,8 @@ void carla_register_native_plugin_Notes(); #ifdef WANT_ZYNADDSUBFX // ZynAddSubFX -void carla_register_native_plugin_zynaddsubfx(); +void carla_register_native_plugin_zynaddsubfx_fx(); +void carla_register_native_plugin_zynaddsubfx_synth(); #endif } @@ -80,7 +82,8 @@ void carla_register_all_plugins() carla_register_native_plugin_midiTranspose(); carla_register_native_plugin_nekofilter(); //carla_register_native_plugin_sunvoxfile(); // unfinished - carla_register_native_plugin_vex(); + carla_register_native_plugin_vex_fx(); + carla_register_native_plugin_vex_synth(); #ifndef BUILD_BRIDGE // Carla @@ -113,7 +116,8 @@ void carla_register_all_plugins() #ifdef WANT_ZYNADDSUBFX // ZynAddSubFX - carla_register_native_plugin_zynaddsubfx(); + carla_register_native_plugin_zynaddsubfx_fx(); + carla_register_native_plugin_zynaddsubfx_synth(); #endif } diff --git a/source/modules/carla_native/Makefile b/source/modules/carla_native/Makefile index 036ec5147..81051a79c 100644 --- a/source/modules/carla_native/Makefile +++ b/source/modules/carla_native/Makefile @@ -55,7 +55,8 @@ OBJS = \ # Simple plugins (C++) OBJS += \ - vex.cpp.o \ + vex-fx.cpp.o \ + vex-synth.cpp.o \ vex-src.cpp.o # AudioFile @@ -92,7 +93,8 @@ OBJS += \ ifeq ($(HAVE_ZYN_DEPS),true) # ZynAddSubFX OBJS += \ - zynaddsubfx.cpp.o \ + zynaddsubfx-fx.cpp.o \ + zynaddsubfx-synth.cpp.o \ zynaddsubfx-src.cpp.o ifeq ($(HAVE_ZYN_UI_DEPS),true) @@ -199,13 +201,10 @@ midi-sequencer.cpp.o: midi-sequencer.cpp midi-base.hpp $(CXXDEPS) nekofilter.c.o: nekofilter.c nekofilter/*.c nekofilter/*.h $(CDEPS) $(CC) $< $(BUILD_C_FLAGS) -c -o $@ -zynaddsubfx.cpp.o: zynaddsubfx.cpp $(CXXDEPS) $(ZYN_UI_FILES_H) - $(CXX) $< $(ZYN_CXX_FLAGS) -c -o $@ - -zynaddsubfx-src.cpp.o: zynaddsubfx-src.cpp $(ZYN_UI_FILES_H) +zynaddsubfx-ui.cpp.o: zynaddsubfx-ui.cpp $(ZYN_UI_FILES_H) $(ZYN_UI_FILES_CPP) $(CXX) $< $(ZYN_CXX_FLAGS) -c -o $@ -zynaddsubfx-ui.cpp.o: zynaddsubfx-ui.cpp $(ZYN_UI_FILES_H) $(ZYN_UI_FILES_CPP) +zynaddsubfx-%.cpp.o: zynaddsubfx-%.cpp $(CXXDEPS) $(ZYN_UI_FILES_H) $(CXX) $< $(ZYN_CXX_FLAGS) -c -o $@ zynaddsubfx/UI/%.cpp: zynaddsubfx/UI/%.fl diff --git a/source/modules/carla_native/vex.cpp b/source/modules/carla_native/vex-fx.cpp similarity index 59% rename from source/modules/carla_native/vex.cpp rename to source/modules/carla_native/vex-fx.cpp index 15f9d4899..a562b1376 100644 --- a/source/modules/carla_native/vex.cpp +++ b/source/modules/carla_native/vex-fx.cpp @@ -17,7 +17,7 @@ #include "CarlaNative.hpp" -#include "juce_core.h" +#include "juce_gui_basics.h" using namespace juce; @@ -25,13 +25,8 @@ using namespace juce; #include "vex/VexChorus.h" #include "vex/VexDelay.h" #include "vex/VexReverb.h" -#include "vex/VexSyntModule.h" #include "vex/PeggyViewComponent.h" -#include "vex/lookandfeel/MyLookAndFeel.h" -#include "vex/resources/Resources.h" - -#include "vex/resources/Resources.cpp" // ----------------------------------------------------------------------- @@ -96,139 +91,6 @@ private: // ----------------------------------------------------------------------- -class VexEditorComponent : public ComboBox::Listener, - public Slider::Listener, - public Button::Listener, - public ChangeListener, - public Component, - public PeggyViewComponent::Callback -{ -public: - VexEditorComponent() - { - internalCachedImage1 = ImageCache::getFromMemory(Resources::vex3_png, Resources::vex3_pngSize); - - // Comboboxes, wave selection - addAndMakeVisible(comboBox1 = new ComboBox (String::empty)); - comboBox1->setEditableText(false); - comboBox1->setJustificationType(Justification::centredLeft); - comboBox1->setTextWhenNothingSelected(String("silent")); - comboBox1->setTextWhenNoChoicesAvailable(String("silent")); - comboBox1->addListener(this); - comboBox1->setColour(ComboBox::backgroundColourId, Colours::black); - comboBox1->setColour(ComboBox::textColourId, Colours::lightgrey); - comboBox1->setColour(ComboBox::outlineColourId, Colours::grey); - comboBox1->setColour(ComboBox::buttonColourId, Colours::grey); - comboBox1->setWantsKeyboardFocus(false); - comboBox1->setLookAndFeel(&mlaf); - - addAndMakeVisible (comboBox2 = new ComboBox (String::empty)); - comboBox2->setEditableText (false); - comboBox2->setJustificationType (Justification::centredLeft); - comboBox2->setTextWhenNothingSelected (String("silent")); - comboBox2->setTextWhenNoChoicesAvailable (String("silent")); - comboBox2->addListener (this); - comboBox2->setColour(ComboBox::backgroundColourId, Colours::black); - comboBox2->setColour(ComboBox::textColourId, Colours::lightgrey); - comboBox2->setColour(ComboBox::outlineColourId, Colours::grey); - comboBox2->setColour(ComboBox::buttonColourId, Colours::grey); - comboBox2->setWantsKeyboardFocus(false); - comboBox2->setLookAndFeel(&mlaf); - - addAndMakeVisible (comboBox3 = new ComboBox (String::empty)); - comboBox3->setEditableText (false); - comboBox3->setJustificationType (Justification::centredLeft); - comboBox3->setTextWhenNothingSelected (String("silent")); - comboBox3->setTextWhenNoChoicesAvailable (String("silent")); - comboBox3->addListener (this); - comboBox3->setColour(ComboBox::backgroundColourId, Colours::black); - comboBox3->setColour(ComboBox::textColourId, Colours::lightgrey); - comboBox3->setColour(ComboBox::outlineColourId, Colours::grey); - comboBox3->setColour(ComboBox::buttonColourId, Colours::grey); - comboBox3->setWantsKeyboardFocus(false); - comboBox3->setLookAndFeel(&mlaf); - - for (int i = 0, tableSize = WaveRenderer::getWaveTableSize(); i < tableSize; ++i) - { - String tableName(WaveRenderer::getWaveTableName(i)); - - comboBox1->addItem(tableName, i + 1); - comboBox2->addItem(tableName, i + 1); - comboBox3->addItem(tableName, i + 1); - } - - addChildComponent(p1 = new PeggyViewComponent(1, _d, this)); - p1->setLookAndFeel(&mlaf); - addChildComponent(p2 = new PeggyViewComponent(2, _d, this)); - p2->setLookAndFeel(&mlaf); - addChildComponent(p3 = new PeggyViewComponent(3, _d, this)); - p3->setLookAndFeel(&mlaf); - - //ownerFilter->addChangeListener (this); - setSize(800,500); - } - - ~VexEditorComponent() - { - removeAllChildren(); - } - -protected: - void paint(Graphics& g) override - { - g.drawImage(internalCachedImage1, - 0, 0, 800, 500, - 0, 0, internalCachedImage1.getWidth(), internalCachedImage1.getHeight()); - } - - void resized() override - { - comboBox1->setBounds(13, 38, 173, 23); - comboBox2->setBounds(213, 38, 173, 23); - comboBox3->setBounds(413, 38, 173, 23); - - p1->setBounds(10, 20, 207, 280); - p2->setBounds(210, 20, 207, 280); - p3->setBounds(410, 20, 207, 280); - } - - void changeListenerCallback(ChangeBroadcaster* source) override - { - } - - void comboBoxChanged(ComboBox* comboBoxThatHasChanged) override - { - } - - void sliderValueChanged(Slider* sliderThatWasMoved) override - { - } - - void buttonClicked(Button* buttonThatWasClicked) override - { - } - - void somethingChanged(const uint32_t id) override - { - } - -private: - Image internalCachedImage1; - MyLookAndFeel mlaf; - - ScopedPointer comboBox1; - ScopedPointer comboBox2; - ScopedPointer comboBox3; - - ScopedPointer p1; - ScopedPointer p2; - ScopedPointer p3; - - VexArpSettings _d; -}; - -// ----------------------------------------------------------------------- - class VexArpPlugin : public PluginClass, public PeggyViewComponent::Callback { @@ -1009,469 +871,6 @@ private: // ----------------------------------------------------------------------- -class VexSynthPlugin : public PluginClass -{ -public: - static const unsigned int kParamCount = 92; - - VexSynthPlugin(const HostDescriptor* const host) - : PluginClass(host), - obf(nullptr), - abf(nullptr), - dbf1(nullptr), - dbf2(nullptr), - dbf3(nullptr), - fChorus(fParameters), - fDelay(fParameters), - fReverb(fParameters), - fSynth(fParameters) - { - std::memset(fParameters, 0, sizeof(float)*92); - - fParameters[0] = 1.0f; // main volume - - for (int i = 0; i < 3; ++i) - { - const int offset = i * 24; - - fParameters[offset + 1] = 0.5f; - fParameters[offset + 2] = 0.5f; - fParameters[offset + 3] = 0.5f; - fParameters[offset + 4] = 0.5f; - fParameters[offset + 5] = 0.9f; - fParameters[offset + 6] = 0.0f; - fParameters[offset + 7] = 1.0f; - fParameters[offset + 8] = 0.5f; - fParameters[offset + 9] = 0.0f; - fParameters[offset + 10] = 0.2f; - fParameters[offset + 11] = 0.0f; - fParameters[offset + 12] = 0.5f; - fParameters[offset + 13] = 0.5f; - fParameters[offset + 14] = 0.0f; - fParameters[offset + 15] = 0.3f; - fParameters[offset + 16] = 0.7f; - fParameters[offset + 17] = 0.1f; - fParameters[offset + 18] = 0.5f; - fParameters[offset + 19] = 0.5f; - fParameters[offset + 20] = 0.0f; - fParameters[offset + 21] = 0.0f; - fParameters[offset + 22] = 0.5f; - fParameters[offset + 23] = 0.5f; - fParameters[offset + 24] = 0.5f; - } - - // ^1 - 72 - - fParameters[73] = 0.5f; // Delay Time - fParameters[74] = 0.4f; // Delay Feedback - fParameters[75] = 0.0f; // Delay Volume - - fParameters[76] = 0.3f; // Chorus Rate - fParameters[77] = 0.6f; // Chorus Depth - fParameters[78] = 0.5f; // Chorus Volume - - fParameters[79] = 0.6f; // Reverb Size - fParameters[80] = 0.7f; // Reverb Width - fParameters[81] = 0.6f; // Reverb Damp - fParameters[82] = 0.0f; // Reverb Volume - - fParameters[83] = 0.5f; // wave1 panning - fParameters[84] = 0.5f; // wave2 panning - fParameters[85] = 0.5f; // wave3 panning - - fParameters[86] = 0.5f; // wave1 volume - fParameters[87] = 0.5f; // wave2 volume - fParameters[88] = 0.5f; // wave3 volume - - fParameters[89] = 1.0f; // wave1 on/off - fParameters[90] = 1.0f; // wave2 on/off - fParameters[91] = 1.0f; // wave3 on/off - - bufferSizeChanged(getBufferSize()); - sampleRateChanged(getSampleRate()); - } - - ~VexSynthPlugin() - { - delete obf; - delete abf; - delete dbf1; - delete dbf2; - delete dbf3; - } - -protected: - // ------------------------------------------------------------------- - // Plugin parameter calls - - uint32_t getParameterCount() const override - { - return kParamCount; - } - - const Parameter* getParameterInfo(const uint32_t index) const override - { - static Parameter paramInfo; - - int hints = PARAMETER_IS_ENABLED|PARAMETER_IS_AUTOMABLE; - - paramInfo.name = nullptr; - paramInfo.unit = nullptr; - paramInfo.ranges.def = 0.0f; - paramInfo.ranges.min = 0.0f; - paramInfo.ranges.max = 1.0f; - paramInfo.ranges.step = PARAMETER_RANGES_DEFAULT_STEP; - paramInfo.ranges.stepSmall = PARAMETER_RANGES_DEFAULT_STEP_SMALL; - paramInfo.ranges.stepLarge = PARAMETER_RANGES_DEFAULT_STEP_LARGE; - paramInfo.scalePointCount = 0; - paramInfo.scalePoints = nullptr; - - if (index >= 1 && index <= 72) - { - uint32_t ri = index % 24; - - switch (ri) - { - case 1: - paramInfo.name = "oct"; - break; - case 2: - paramInfo.name = "cent"; - break; - case 3: - paramInfo.name = "phaseOffset"; - break; - case 4: - paramInfo.name = "phaseIncOffset"; - break; - case 5: - paramInfo.name = "filter"; - break; - case 6: - paramInfo.name = "filter"; - break; - case 7: - paramInfo.name = "filter"; - break; - case 8: - paramInfo.name = "filter"; - break; - case 9: - paramInfo.name = "F ADSR"; - break; - case 10: - paramInfo.name = "F ADSR"; - break; - case 11: - paramInfo.name = "F ADSR"; - break; - case 12: - paramInfo.name = "F ADSR"; - break; - case 13: - paramInfo.name = "F velocity"; - break; - case 14: - paramInfo.name = "A ADSR"; - break; - case 15: - paramInfo.name = "A ADSR"; - break; - case 16: - paramInfo.name = "A ADSR"; - break; - case 17: - paramInfo.name = "A ADSR"; - break; - case 18: - paramInfo.name = "A velocity"; - break; - case 19: - paramInfo.name = "lfoC"; - break; - case 20: - paramInfo.name = "lfoA"; - break; - case 21: - paramInfo.name = "lfoF"; - break; - case 22: - paramInfo.name = "fx vol D"; - break; - case 23: - paramInfo.name = "fx vol C"; - break; - case 24: - case 0: - paramInfo.name = "fx vol R"; - break; - default: - paramInfo.name = "unknown2"; - break; - } - - paramInfo.hints = static_cast(hints); - return ¶mInfo; - } - - switch (index) - { - case 0: - paramInfo.name = "Main volume"; - break; - case 73: - paramInfo.name = "Delay Time"; - break; - case 74: - paramInfo.name = "Delay Feedback"; - break; - case 75: - paramInfo.name = "Delay Volume"; - break; - case 76: - paramInfo.name = "Chorus Rate"; - break; - case 77: - paramInfo.name = "Chorus Depth"; - break; - case 78: - paramInfo.name = "Chorus Volume"; - break; - case 79: - paramInfo.name = "Reverb Size"; - break; - case 80: - paramInfo.name = "Reverb Width"; - break; - case 81: - paramInfo.name = "Reverb Damp"; - break; - case 82: - paramInfo.name = "Reverb Volume"; - break; - case 83: - paramInfo.name = "Wave1 Panning"; - break; - case 84: - paramInfo.name = "Wave2 Panning"; - break; - case 85: - paramInfo.name = "Wave3 Panning"; - break; - case 86: - paramInfo.name = "Wave1 Volume"; - break; - case 87: - paramInfo.name = "Wave2 Volume"; - break; - case 88: - paramInfo.name = "Wave3 Volume"; - break; - case 89: - paramInfo.name = "Wave1 on/off"; - break; - case 90: - paramInfo.name = "Wave2 on/off"; - break; - case 91: - paramInfo.name = "Wave3 on/off"; - break; - default: - paramInfo.name = "unknown"; - break; - } - - paramInfo.hints = static_cast(hints); - return ¶mInfo; - } - - float getParameterValue(const uint32_t index) const override - { - return (index < kParamCount) ? fParameters[index] : 0.0f; - } - - // ------------------------------------------------------------------- - // Plugin state calls - - void setParameterValue(const uint32_t index, const float value) override - { - if (index < kParamCount) - { - fParameters[index] = value; - fSynth.update(index); - } - } - - // ------------------------------------------------------------------- - // Plugin process calls - - void process(float**, float** outBuffer, const uint32_t frames, const MidiEvent* const midiEvents, const uint32_t midiEventCount) override - { - const TimeInfo* const timeInfo(getTimeInfo()); - const double bpm((timeInfo != nullptr && timeInfo->bbt.valid) ? timeInfo->bbt.beatsPerMinute : 120.0); - - for (uint32_t i=0; i < midiEventCount; ++i) - { - const MidiEvent* const midiEvent(&midiEvents[i]); - - const uint8_t status(MIDI_GET_STATUS_FROM_DATA(midiEvent->data)); - - if (status == MIDI_STATUS_NOTE_ON) - { - fSynth.playNote(midiEvent->data[1], midiEvent->data[2], 0, 1); - } - else if (status == MIDI_STATUS_NOTE_OFF) - { - fSynth.releaseNote(midiEvent->data[1], 0, 1); - } - else if (status == MIDI_STATUS_CONTROL_CHANGE) - { - const uint8_t control(midiEvent->data[1]); - - if (control == MIDI_CONTROL_ALL_SOUND_OFF) - fSynth.kill(); - else if (control == MIDI_CONTROL_ALL_NOTES_OFF) - fSynth.releaseAll(1); - } - } - - if (obf->getNumSamples() != (int)frames) - { - obf->setSize(2, frames, 0, 0, 1); - abf->setSize(2, frames, 0, 0, 1); - dbf1->setSize(2, frames, 0, 0, 1); - dbf2->setSize(2, frames, 0, 0, 1); - dbf3->setSize(2, frames, 0, 0, 1); - } - - obf ->clear(); - dbf1->clear(); - dbf2->clear(); - dbf3->clear(); - - fSynth.doProcess(*obf, *abf, *dbf1, *dbf2, *dbf3); - - if (fParameters[75] > 0.001f) fDelay.processBlock(dbf1, bpm); - if (fParameters[78] > 0.001f) fChorus.processBlock(dbf2); - if (fParameters[82] > 0.001f) fReverb.processBlock(dbf3); - - AudioSampleBuffer output(outBuffer, 2, 0, frames); - output.clear(); - - obf->addFrom(0, 0, *dbf1, 0, 0, frames, fParameters[75]); - obf->addFrom(1, 0, *dbf1, 1, 0, frames, fParameters[75]); - obf->addFrom(0, 0, *dbf2, 0, 0, frames, fParameters[78]); - obf->addFrom(1, 0, *dbf2, 1, 0, frames, fParameters[78]); - obf->addFrom(0, 0, *dbf3, 0, 0, frames, fParameters[82]); - obf->addFrom(1, 0, *dbf3, 1, 0, frames, fParameters[82]); - - output.addFrom(0, 0, *obf, 0, 0, frames, fParameters[0]); - output.addFrom(1, 0, *obf, 1, 0, frames, fParameters[0]); - } - - // ------------------------------------------------------------------- - // Plugin UI calls - - void uiShow(const bool show) override - { - if (show) - { - if (fWindow == nullptr) - { - fWindow = new HelperWindow(); - fWindow->setName(getUiName()); - } - - if (fView == nullptr) - fView = new VexEditorComponent(); - - fWindow->show(fView); - } - else if (fWindow != nullptr) - { - fWindow->hide(); - - fView = nullptr; - fWindow = nullptr; - } - } - - void uiIdle() override - { - if (fWindow == nullptr) - return; - - if (fWindow->wasClosedByUser()) - { - uiShow(false); - uiClosed(); - } - } - - void uiSetParameterValue(const uint32_t, const float) override - { - if (fView == nullptr) - return; - - //fView->update(); - } - - // ------------------------------------------------------------------- - // Plugin dispatcher calls - - void bufferSizeChanged(const uint32_t bufferSize) override - { - delete obf; - delete abf; - delete dbf1; - delete dbf2; - delete dbf3; - - obf = new AudioSampleBuffer(2, bufferSize); - abf = new AudioSampleBuffer(2, bufferSize); - dbf1 = new AudioSampleBuffer(2, bufferSize); - dbf2 = new AudioSampleBuffer(2, bufferSize); - dbf3 = new AudioSampleBuffer(2, bufferSize); - } - - void sampleRateChanged(const double sampleRate) override - { - fChorus.setSampleRate(sampleRate); - fDelay.setSampleRate(sampleRate); - fSynth.setSampleRate(sampleRate); - } - - void uiNameChanged(const char* const uiName) override - { - if (fWindow == nullptr) - return; - - fWindow->setName(uiName); - } - -private: - float fParameters[92]; - - AudioSampleBuffer* obf; - AudioSampleBuffer* abf; - AudioSampleBuffer* dbf1; // delay - AudioSampleBuffer* dbf2; // chorus - AudioSampleBuffer* dbf3; // reverb - - VexChorus fChorus; - VexDelay fDelay; - VexReverb fReverb; - VexSyntModule fSynth; - - ScopedPointer fView; - ScopedPointer fWindow; - - PluginClassEND(VexSynthPlugin) - CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(VexSynthPlugin) -}; - -// ----------------------------------------------------------------------- - static const PluginDescriptor vexArpDesc = { /* category */ PLUGIN_CATEGORY_UTILITY, /* hints */ static_cast(PLUGIN_HAS_GUI|PLUGIN_NEEDS_SINGLE_THREAD|PLUGIN_USES_TIME), @@ -1540,33 +939,15 @@ static const PluginDescriptor vexReverbDesc = { PluginDescriptorFILL(VexReverbPlugin) }; -static const PluginDescriptor vexSynthDesc = { - /* category */ PLUGIN_CATEGORY_SYNTH, - /* hints */ static_cast(PLUGIN_HAS_GUI|PLUGIN_NEEDS_SINGLE_THREAD|PLUGIN_USES_TIME), - /* supports */ static_cast(0x0), - /* audioIns */ 0, - /* audioOuts */ 2, - /* midiIns */ 1, - /* midiOuts */ 0, - /* paramIns */ VexSynthPlugin::kParamCount, - /* paramOuts */ 0, - /* name */ "VexSynth", - /* label */ "vexSynth", - /* maker */ "falkTX", - /* copyright */ "GNU GPL v2+", - PluginDescriptorFILL(VexSynthPlugin) -}; - // ----------------------------------------------------------------------- CARLA_EXPORT -void carla_register_native_plugin_vex() +void carla_register_native_plugin_vex_fx() { carla_register_native_plugin(&vexArpDesc); carla_register_native_plugin(&vexChorusDesc); carla_register_native_plugin(&vexDelayDesc); carla_register_native_plugin(&vexReverbDesc); - carla_register_native_plugin(&vexSynthDesc); } // ----------------------------------------------------------------------- diff --git a/source/modules/carla_native/vex-synth.cpp b/source/modules/carla_native/vex-synth.cpp new file mode 100644 index 000000000..0d78fa97f --- /dev/null +++ b/source/modules/carla_native/vex-synth.cpp @@ -0,0 +1,720 @@ +/* + * Carla Native Plugins + * Copyright (C) 2013 Filipe Coelho + * + * This program 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 2 of + * the License, or any later version. + * + * This program 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. + * + * For a full copy of the GNU General Public License see the doc/GPL.txt file. + */ + +#include "CarlaNative.hpp" + +#include "juce_gui_basics.h" + +using namespace juce; + +#include "vex/VexArp.h" +#include "vex/VexChorus.h" +#include "vex/VexDelay.h" +#include "vex/VexReverb.h" +#include "vex/VexSyntModule.h" + +#include "vex/PeggyViewComponent.h" +#include "vex/lookandfeel/MyLookAndFeel.h" +#include "vex/resources/Resources.h" + +#include "vex/resources/Resources.cpp" + +// ----------------------------------------------------------------------- + +class HelperWindow2 : public DocumentWindow +{ +public: + HelperWindow2() + : DocumentWindow("PlugWindow", Colour(50, 50, 200), DocumentWindow::closeButton, false), + fClosed(false) + { + setVisible(false); + setAlwaysOnTop(true); + setDropShadowEnabled(false); + setOpaque(true); + //setResizable(false, false); + //setUsingNativeTitleBar(false); + } + + void show(Component* const comp) + { + fClosed = false; + + const int width = comp->getWidth(); + const int height = comp->getHeight()+getTitleBarHeight(); + + centreWithSize(width, height); + setContentNonOwned(comp, false); + setSize(width, height); + + if (! isOnDesktop()) + addToDesktop(); + + setVisible(true); + } + + void hide() + { + setVisible(false); + + if (isOnDesktop()) + removeFromDesktop(); + + clearContentComponent(); + } + + bool wasClosedByUser() const + { + return fClosed; + } + +protected: + void closeButtonPressed() override + { + fClosed = true; + } + +private: + bool fClosed; + + JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(HelperWindow2) +}; + +// ----------------------------------------------------------------------- + +class VexEditorComponent : public ComboBox::Listener, + public Slider::Listener, + public Button::Listener, + public ChangeListener, + public Component, + public PeggyViewComponent::Callback +{ +public: + VexEditorComponent() + { + internalCachedImage1 = ImageCache::getFromMemory(Resources::vex3_png, Resources::vex3_pngSize); + + // Comboboxes, wave selection + addAndMakeVisible(comboBox1 = new ComboBox (String::empty)); + comboBox1->setEditableText(false); + comboBox1->setJustificationType(Justification::centredLeft); + comboBox1->setTextWhenNothingSelected(String("silent")); + comboBox1->setTextWhenNoChoicesAvailable(String("silent")); + comboBox1->addListener(this); + comboBox1->setColour(ComboBox::backgroundColourId, Colours::black); + comboBox1->setColour(ComboBox::textColourId, Colours::lightgrey); + comboBox1->setColour(ComboBox::outlineColourId, Colours::grey); + comboBox1->setColour(ComboBox::buttonColourId, Colours::grey); + comboBox1->setWantsKeyboardFocus(false); + comboBox1->setLookAndFeel(&mlaf); + + addAndMakeVisible (comboBox2 = new ComboBox (String::empty)); + comboBox2->setEditableText (false); + comboBox2->setJustificationType (Justification::centredLeft); + comboBox2->setTextWhenNothingSelected (String("silent")); + comboBox2->setTextWhenNoChoicesAvailable (String("silent")); + comboBox2->addListener (this); + comboBox2->setColour(ComboBox::backgroundColourId, Colours::black); + comboBox2->setColour(ComboBox::textColourId, Colours::lightgrey); + comboBox2->setColour(ComboBox::outlineColourId, Colours::grey); + comboBox2->setColour(ComboBox::buttonColourId, Colours::grey); + comboBox2->setWantsKeyboardFocus(false); + comboBox2->setLookAndFeel(&mlaf); + + addAndMakeVisible (comboBox3 = new ComboBox (String::empty)); + comboBox3->setEditableText (false); + comboBox3->setJustificationType (Justification::centredLeft); + comboBox3->setTextWhenNothingSelected (String("silent")); + comboBox3->setTextWhenNoChoicesAvailable (String("silent")); + comboBox3->addListener (this); + comboBox3->setColour(ComboBox::backgroundColourId, Colours::black); + comboBox3->setColour(ComboBox::textColourId, Colours::lightgrey); + comboBox3->setColour(ComboBox::outlineColourId, Colours::grey); + comboBox3->setColour(ComboBox::buttonColourId, Colours::grey); + comboBox3->setWantsKeyboardFocus(false); + comboBox3->setLookAndFeel(&mlaf); + + for (int i = 0, tableSize = WaveRenderer::getWaveTableSize(); i < tableSize; ++i) + { + String tableName(WaveRenderer::getWaveTableName(i)); + + comboBox1->addItem(tableName, i + 1); + comboBox2->addItem(tableName, i + 1); + comboBox3->addItem(tableName, i + 1); + } + + addChildComponent(p1 = new PeggyViewComponent(1, _d, this)); + p1->setLookAndFeel(&mlaf); + addChildComponent(p2 = new PeggyViewComponent(2, _d, this)); + p2->setLookAndFeel(&mlaf); + addChildComponent(p3 = new PeggyViewComponent(3, _d, this)); + p3->setLookAndFeel(&mlaf); + + //ownerFilter->addChangeListener (this); + setSize(800,500); + } + + ~VexEditorComponent() + { + removeAllChildren(); + } + +protected: + void paint(Graphics& g) override + { + g.drawImage(internalCachedImage1, + 0, 0, 800, 500, + 0, 0, internalCachedImage1.getWidth(), internalCachedImage1.getHeight()); + } + + void resized() override + { + comboBox1->setBounds(13, 38, 173, 23); + comboBox2->setBounds(213, 38, 173, 23); + comboBox3->setBounds(413, 38, 173, 23); + + p1->setBounds(10, 20, 207, 280); + p2->setBounds(210, 20, 207, 280); + p3->setBounds(410, 20, 207, 280); + } + + void changeListenerCallback(ChangeBroadcaster* source) override + { + } + + void comboBoxChanged(ComboBox* comboBoxThatHasChanged) override + { + } + + void sliderValueChanged(Slider* sliderThatWasMoved) override + { + } + + void buttonClicked(Button* buttonThatWasClicked) override + { + } + + void somethingChanged(const uint32_t id) override + { + } + +private: + Image internalCachedImage1; + MyLookAndFeel mlaf; + + ScopedPointer comboBox1; + ScopedPointer comboBox2; + ScopedPointer comboBox3; + + ScopedPointer p1; + ScopedPointer p2; + ScopedPointer p3; + + VexArpSettings _d; +}; + +// ----------------------------------------------------------------------- + +class VexSynthPlugin : public PluginClass +{ +public: + static const unsigned int kParamCount = 92; + + VexSynthPlugin(const HostDescriptor* const host) + : PluginClass(host), + obf(nullptr), + abf(nullptr), + dbf1(nullptr), + dbf2(nullptr), + dbf3(nullptr), + fChorus(fParameters), + fDelay(fParameters), + fReverb(fParameters), + fSynth(fParameters) + { + std::memset(fParameters, 0, sizeof(float)*92); + + fParameters[0] = 1.0f; // main volume + + for (int i = 0; i < 3; ++i) + { + const int offset = i * 24; + + fParameters[offset + 1] = 0.5f; + fParameters[offset + 2] = 0.5f; + fParameters[offset + 3] = 0.5f; + fParameters[offset + 4] = 0.5f; + fParameters[offset + 5] = 0.9f; + fParameters[offset + 6] = 0.0f; + fParameters[offset + 7] = 1.0f; + fParameters[offset + 8] = 0.5f; + fParameters[offset + 9] = 0.0f; + fParameters[offset + 10] = 0.2f; + fParameters[offset + 11] = 0.0f; + fParameters[offset + 12] = 0.5f; + fParameters[offset + 13] = 0.5f; + fParameters[offset + 14] = 0.0f; + fParameters[offset + 15] = 0.3f; + fParameters[offset + 16] = 0.7f; + fParameters[offset + 17] = 0.1f; + fParameters[offset + 18] = 0.5f; + fParameters[offset + 19] = 0.5f; + fParameters[offset + 20] = 0.0f; + fParameters[offset + 21] = 0.0f; + fParameters[offset + 22] = 0.5f; + fParameters[offset + 23] = 0.5f; + fParameters[offset + 24] = 0.5f; + } + + // ^1 - 72 + + fParameters[73] = 0.5f; // Delay Time + fParameters[74] = 0.4f; // Delay Feedback + fParameters[75] = 0.0f; // Delay Volume + + fParameters[76] = 0.3f; // Chorus Rate + fParameters[77] = 0.6f; // Chorus Depth + fParameters[78] = 0.5f; // Chorus Volume + + fParameters[79] = 0.6f; // Reverb Size + fParameters[80] = 0.7f; // Reverb Width + fParameters[81] = 0.6f; // Reverb Damp + fParameters[82] = 0.0f; // Reverb Volume + + fParameters[83] = 0.5f; // wave1 panning + fParameters[84] = 0.5f; // wave2 panning + fParameters[85] = 0.5f; // wave3 panning + + fParameters[86] = 0.5f; // wave1 volume + fParameters[87] = 0.5f; // wave2 volume + fParameters[88] = 0.5f; // wave3 volume + + fParameters[89] = 1.0f; // wave1 on/off + fParameters[90] = 1.0f; // wave2 on/off + fParameters[91] = 1.0f; // wave3 on/off + + bufferSizeChanged(getBufferSize()); + sampleRateChanged(getSampleRate()); + } + + ~VexSynthPlugin() + { + delete obf; + delete abf; + delete dbf1; + delete dbf2; + delete dbf3; + } + +protected: + // ------------------------------------------------------------------- + // Plugin parameter calls + + uint32_t getParameterCount() const override + { + return kParamCount; + } + + const Parameter* getParameterInfo(const uint32_t index) const override + { + static Parameter paramInfo; + + int hints = PARAMETER_IS_ENABLED|PARAMETER_IS_AUTOMABLE; + + paramInfo.name = nullptr; + paramInfo.unit = nullptr; + paramInfo.ranges.def = 0.0f; + paramInfo.ranges.min = 0.0f; + paramInfo.ranges.max = 1.0f; + paramInfo.ranges.step = PARAMETER_RANGES_DEFAULT_STEP; + paramInfo.ranges.stepSmall = PARAMETER_RANGES_DEFAULT_STEP_SMALL; + paramInfo.ranges.stepLarge = PARAMETER_RANGES_DEFAULT_STEP_LARGE; + paramInfo.scalePointCount = 0; + paramInfo.scalePoints = nullptr; + + if (index >= 1 && index <= 72) + { + uint32_t ri = index % 24; + + switch (ri) + { + case 1: + paramInfo.name = "oct"; + break; + case 2: + paramInfo.name = "cent"; + break; + case 3: + paramInfo.name = "phaseOffset"; + break; + case 4: + paramInfo.name = "phaseIncOffset"; + break; + case 5: + paramInfo.name = "filter"; + break; + case 6: + paramInfo.name = "filter"; + break; + case 7: + paramInfo.name = "filter"; + break; + case 8: + paramInfo.name = "filter"; + break; + case 9: + paramInfo.name = "F ADSR"; + break; + case 10: + paramInfo.name = "F ADSR"; + break; + case 11: + paramInfo.name = "F ADSR"; + break; + case 12: + paramInfo.name = "F ADSR"; + break; + case 13: + paramInfo.name = "F velocity"; + break; + case 14: + paramInfo.name = "A ADSR"; + break; + case 15: + paramInfo.name = "A ADSR"; + break; + case 16: + paramInfo.name = "A ADSR"; + break; + case 17: + paramInfo.name = "A ADSR"; + break; + case 18: + paramInfo.name = "A velocity"; + break; + case 19: + paramInfo.name = "lfoC"; + break; + case 20: + paramInfo.name = "lfoA"; + break; + case 21: + paramInfo.name = "lfoF"; + break; + case 22: + paramInfo.name = "fx vol D"; + break; + case 23: + paramInfo.name = "fx vol C"; + break; + case 24: + case 0: + paramInfo.name = "fx vol R"; + break; + default: + paramInfo.name = "unknown2"; + break; + } + + paramInfo.hints = static_cast(hints); + return ¶mInfo; + } + + switch (index) + { + case 0: + paramInfo.name = "Main volume"; + break; + case 73: + paramInfo.name = "Delay Time"; + break; + case 74: + paramInfo.name = "Delay Feedback"; + break; + case 75: + paramInfo.name = "Delay Volume"; + break; + case 76: + paramInfo.name = "Chorus Rate"; + break; + case 77: + paramInfo.name = "Chorus Depth"; + break; + case 78: + paramInfo.name = "Chorus Volume"; + break; + case 79: + paramInfo.name = "Reverb Size"; + break; + case 80: + paramInfo.name = "Reverb Width"; + break; + case 81: + paramInfo.name = "Reverb Damp"; + break; + case 82: + paramInfo.name = "Reverb Volume"; + break; + case 83: + paramInfo.name = "Wave1 Panning"; + break; + case 84: + paramInfo.name = "Wave2 Panning"; + break; + case 85: + paramInfo.name = "Wave3 Panning"; + break; + case 86: + paramInfo.name = "Wave1 Volume"; + break; + case 87: + paramInfo.name = "Wave2 Volume"; + break; + case 88: + paramInfo.name = "Wave3 Volume"; + break; + case 89: + paramInfo.name = "Wave1 on/off"; + break; + case 90: + paramInfo.name = "Wave2 on/off"; + break; + case 91: + paramInfo.name = "Wave3 on/off"; + break; + default: + paramInfo.name = "unknown"; + break; + } + + paramInfo.hints = static_cast(hints); + return ¶mInfo; + } + + float getParameterValue(const uint32_t index) const override + { + return (index < kParamCount) ? fParameters[index] : 0.0f; + } + + // ------------------------------------------------------------------- + // Plugin state calls + + void setParameterValue(const uint32_t index, const float value) override + { + if (index < kParamCount) + { + fParameters[index] = value; + fSynth.update(index); + } + } + + // ------------------------------------------------------------------- + // Plugin process calls + + void process(float**, float** outBuffer, const uint32_t frames, const MidiEvent* const midiEvents, const uint32_t midiEventCount) override + { + const TimeInfo* const timeInfo(getTimeInfo()); + const double bpm((timeInfo != nullptr && timeInfo->bbt.valid) ? timeInfo->bbt.beatsPerMinute : 120.0); + + for (uint32_t i=0; i < midiEventCount; ++i) + { + const MidiEvent* const midiEvent(&midiEvents[i]); + + const uint8_t status(MIDI_GET_STATUS_FROM_DATA(midiEvent->data)); + + if (status == MIDI_STATUS_NOTE_ON) + { + fSynth.playNote(midiEvent->data[1], midiEvent->data[2], 0, 1); + } + else if (status == MIDI_STATUS_NOTE_OFF) + { + fSynth.releaseNote(midiEvent->data[1], 0, 1); + } + else if (status == MIDI_STATUS_CONTROL_CHANGE) + { + const uint8_t control(midiEvent->data[1]); + + if (control == MIDI_CONTROL_ALL_SOUND_OFF) + fSynth.kill(); + else if (control == MIDI_CONTROL_ALL_NOTES_OFF) + fSynth.releaseAll(1); + } + } + + if (obf->getNumSamples() != (int)frames) + { + obf->setSize(2, frames, 0, 0, 1); + abf->setSize(2, frames, 0, 0, 1); + dbf1->setSize(2, frames, 0, 0, 1); + dbf2->setSize(2, frames, 0, 0, 1); + dbf3->setSize(2, frames, 0, 0, 1); + } + + obf ->clear(); + dbf1->clear(); + dbf2->clear(); + dbf3->clear(); + + fSynth.doProcess(*obf, *abf, *dbf1, *dbf2, *dbf3); + + if (fParameters[75] > 0.001f) fDelay.processBlock(dbf1, bpm); + if (fParameters[78] > 0.001f) fChorus.processBlock(dbf2); + if (fParameters[82] > 0.001f) fReverb.processBlock(dbf3); + + AudioSampleBuffer output(outBuffer, 2, 0, frames); + output.clear(); + + obf->addFrom(0, 0, *dbf1, 0, 0, frames, fParameters[75]); + obf->addFrom(1, 0, *dbf1, 1, 0, frames, fParameters[75]); + obf->addFrom(0, 0, *dbf2, 0, 0, frames, fParameters[78]); + obf->addFrom(1, 0, *dbf2, 1, 0, frames, fParameters[78]); + obf->addFrom(0, 0, *dbf3, 0, 0, frames, fParameters[82]); + obf->addFrom(1, 0, *dbf3, 1, 0, frames, fParameters[82]); + + output.addFrom(0, 0, *obf, 0, 0, frames, fParameters[0]); + output.addFrom(1, 0, *obf, 1, 0, frames, fParameters[0]); + } + + // ------------------------------------------------------------------- + // Plugin UI calls + + void uiShow(const bool show) override + { + if (show) + { + if (fWindow == nullptr) + { + fWindow = new HelperWindow2(); + fWindow->setName(getUiName()); + } + + if (fView == nullptr) + fView = new VexEditorComponent(); + + fWindow->show(fView); + } + else if (fWindow != nullptr) + { + fWindow->hide(); + + fView = nullptr; + fWindow = nullptr; + } + } + + void uiIdle() override + { + if (fWindow == nullptr) + return; + + if (fWindow->wasClosedByUser()) + { + uiShow(false); + uiClosed(); + } + } + + void uiSetParameterValue(const uint32_t, const float) override + { + if (fView == nullptr) + return; + + //fView->update(); + } + + // ------------------------------------------------------------------- + // Plugin dispatcher calls + + void bufferSizeChanged(const uint32_t bufferSize) override + { + delete obf; + delete abf; + delete dbf1; + delete dbf2; + delete dbf3; + + obf = new AudioSampleBuffer(2, bufferSize); + abf = new AudioSampleBuffer(2, bufferSize); + dbf1 = new AudioSampleBuffer(2, bufferSize); + dbf2 = new AudioSampleBuffer(2, bufferSize); + dbf3 = new AudioSampleBuffer(2, bufferSize); + } + + void sampleRateChanged(const double sampleRate) override + { + fChorus.setSampleRate(sampleRate); + fDelay.setSampleRate(sampleRate); + fSynth.setSampleRate(sampleRate); + } + + void uiNameChanged(const char* const uiName) override + { + if (fWindow == nullptr) + return; + + fWindow->setName(uiName); + } + +private: + float fParameters[92]; + + AudioSampleBuffer* obf; + AudioSampleBuffer* abf; + AudioSampleBuffer* dbf1; // delay + AudioSampleBuffer* dbf2; // chorus + AudioSampleBuffer* dbf3; // reverb + + VexChorus fChorus; + VexDelay fDelay; + VexReverb fReverb; + VexSyntModule fSynth; + + ScopedPointer fView; + ScopedPointer fWindow; + + PluginClassEND(VexSynthPlugin) + CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(VexSynthPlugin) +}; + +// ----------------------------------------------------------------------- + +static const PluginDescriptor vexSynthDesc = { + /* category */ PLUGIN_CATEGORY_SYNTH, + /* hints */ static_cast(PLUGIN_HAS_GUI|PLUGIN_NEEDS_SINGLE_THREAD|PLUGIN_USES_TIME), + /* supports */ static_cast(0x0), + /* audioIns */ 0, + /* audioOuts */ 2, + /* midiIns */ 1, + /* midiOuts */ 0, + /* paramIns */ VexSynthPlugin::kParamCount, + /* paramOuts */ 0, + /* name */ "VexSynth", + /* label */ "vexSynth", + /* maker */ "falkTX", + /* copyright */ "GNU GPL v2+", + PluginDescriptorFILL(VexSynthPlugin) +}; + +// ----------------------------------------------------------------------- + +CARLA_EXPORT +void carla_register_native_plugin_vex_synth() +{ + carla_register_native_plugin(&vexSynthDesc); +} + +// ----------------------------------------------------------------------- diff --git a/source/modules/carla_native/zynaddsubfx.cpp b/source/modules/carla_native/zynaddsubfx-fx.cpp similarity index 63% rename from source/modules/carla_native/zynaddsubfx.cpp rename to source/modules/carla_native/zynaddsubfx-fx.cpp index efab82d86..54b805e65 100644 --- a/source/modules/carla_native/zynaddsubfx.cpp +++ b/source/modules/carla_native/zynaddsubfx-fx.cpp @@ -15,18 +15,7 @@ * For a full copy of the GNU General Public License see the doc/GPL.txt file. */ -// for UINT32_MAX -#define __STDC_LIMIT_MACROS -#include - #include "CarlaNative.hpp" -#include "CarlaMIDI.h" -#include "CarlaString.hpp" -#include "RtList.hpp" - -#include "zynaddsubfx/Misc/Master.h" -#include "zynaddsubfx/Misc/Part.h" -#include "zynaddsubfx/Misc/Util.h" #include "zynaddsubfx/Effects/Alienwah.h" #include "zynaddsubfx/Effects/Chorus.h" @@ -36,535 +25,6 @@ #include "zynaddsubfx/Effects/Phaser.h" #include "zynaddsubfx/Effects/Reverb.h" -#ifdef WANT_ZYNADDSUBFX_UI -# ifdef override -# define override_hack -# undef override -# endif - -# include "zynaddsubfx/UI/common.H" -# include "zynaddsubfx/UI/MasterUI.h" -# include -# include -# include - -# ifdef override_hack -# define override -# undef override_hack -# endif -#endif - -#include -#include -#include - -#include "juce_core.h" - -// Dummy variables and functions for linking purposes -const char* instance_name = nullptr; -class WavFile; -namespace Nio { - bool start(void){return 1;} - void stop(void){} - bool setSource(std::string){return true;} - bool setSink(std::string){return true;} - std::set getSources(void){return std::set();} - std::set getSinks(void){return std::set();} - std::string getSource(void){return "";} - std::string getSink(void){return "";} - void waveNew(WavFile*){} - void waveStart(void){} - void waveStop(void){} - void waveEnd(void){} -} - -SYNTH_T* synth = nullptr; - -#ifdef WANT_ZYNADDSUBFX_UI - -static Fl_Tiled_Image* gModuleBackdrop = nullptr; -static CarlaString gPixmapPath; -extern CarlaString gUiPixmapPath; - -void set_module_parameters(Fl_Widget* o) -{ - CARLA_ASSERT(gModuleBackdrop != nullptr); - - o->box(FL_DOWN_FRAME); - o->align(o->align() | FL_ALIGN_IMAGE_BACKDROP); - o->color(FL_BLACK); - o->labeltype(FL_SHADOW_LABEL); - - if (gModuleBackdrop != nullptr) - o->image(gModuleBackdrop); -} -#endif - -// ----------------------------------------------------------------------- - -class ZynAddSubFxPrograms -{ -public: - ZynAddSubFxPrograms() - : fInitiated(false) - { - } - - ~ZynAddSubFxPrograms() - { - if (! fInitiated) - return; - - for (auto it = fPrograms.begin(); it.valid(); it.next()) - { - const ProgramInfo*& pInfo(*it); - delete pInfo; - } - - fPrograms.clear(); - } - - void init() - { - if (fInitiated) - return; - fInitiated = true; - - fPrograms.append(new ProgramInfo(0, 0, "default")); - - Master& master(Master::getInstance()); - - pthread_mutex_lock(&master.mutex); - - // refresh banks - master.bank.rescanforbanks(); - - for (uint32_t i=0, size = master.bank.banks.size(); i < size; ++i) - { - if (master.bank.banks[i].dir.empty()) - continue; - - master.bank.loadbank(master.bank.banks[i].dir); - - for (unsigned int instrument = 0; instrument < BANK_SIZE; ++instrument) - { - const std::string insName(master.bank.getname(instrument)); - - if (insName.empty() || insName[0] == '\0' || insName[0] == ' ') - continue; - - fPrograms.append(new ProgramInfo(i+1, instrument, insName.c_str())); - } - } - - pthread_mutex_unlock(&master.mutex); - } - - void load(Master* const master, const uint8_t channel, const uint32_t bank, const uint32_t program) - { - if (bank == 0) - { - pthread_mutex_lock(&master->mutex); - - master->partonoff(channel, 1); - master->part[channel]->defaults(); - master->part[channel]->applyparameters(false); - - pthread_mutex_unlock(&master->mutex); - - return; - } - - const std::string& bankdir(master->bank.banks[bank-1].dir); - - if (! bankdir.empty()) - { - pthread_mutex_lock(&master->mutex); - - master->partonoff(channel, 1); - - master->bank.loadbank(bankdir); - master->bank.loadfromslot(program, master->part[channel]); - - master->part[channel]->applyparameters(false); - - pthread_mutex_unlock(&master->mutex); - } - } - - uint32_t count() - { - return fPrograms.count(); - } - - const MidiProgram* getInfo(const uint32_t index) - { - if (index >= fPrograms.count()) - return nullptr; - - const ProgramInfo*& pInfo(fPrograms.getAt(index)); - - fRetProgram.bank = pInfo->bank; - fRetProgram.program = pInfo->prog; - fRetProgram.name = pInfo->name; - - return &fRetProgram; - } - -private: - struct ProgramInfo { - uint32_t bank; - uint32_t prog; - const char* name; - - ProgramInfo(uint32_t bank_, uint32_t prog_, const char* name_) - : bank(bank_), - prog(prog_), - name(carla_strdup(name_)) {} - - ~ProgramInfo() - { - if (name != nullptr) - { - delete[] name; - name = nullptr; - } - } - -#ifdef CARLA_PROPER_CPP11_SUPPORT - ProgramInfo() = delete; - ProgramInfo(ProgramInfo&) = delete; - ProgramInfo(const ProgramInfo&) = delete; - ProgramInfo& operator=(ProgramInfo&); - ProgramInfo& operator=(const ProgramInfo&); -#endif - }; - - bool fInitiated; - MidiProgram fRetProgram; - NonRtList fPrograms; - - CARLA_DECLARE_NON_COPY_CLASS(ZynAddSubFxPrograms) -}; - -static ZynAddSubFxPrograms sPrograms; - -// ----------------------------------------------------------------------- - -class ZynAddSubFxInstanceCount -{ -public: - ZynAddSubFxInstanceCount() - : fCount(0) - { - } - - ~ZynAddSubFxInstanceCount() - { - CARLA_ASSERT(fCount == 0); - } - - void addOne(const HostDescriptor* const host) - { - if (fCount++ == 0) - { - CARLA_ASSERT(synth == nullptr); - CARLA_ASSERT(denormalkillbuf == nullptr); - - reinit(host); - -#ifdef WANT_ZYNADDSUBFX_UI - if (gPixmapPath.isEmpty()) - { - gPixmapPath = host->resourceDir; - gPixmapPath += "/zynaddsubfx/"; - gUiPixmapPath = gPixmapPath; - } -#endif - } - } - - void removeOne() - { - if (--fCount == 0) - { - CARLA_ASSERT(synth != nullptr); - CARLA_ASSERT(denormalkillbuf != nullptr); - - Master::deleteInstance(); - - delete[] denormalkillbuf; - denormalkillbuf = nullptr; - - delete synth; - synth = nullptr; - } - } - - void reinit(const HostDescriptor* const host) - { - Master::deleteInstance(); - - if (denormalkillbuf != nullptr) - { - delete[] denormalkillbuf; - denormalkillbuf = nullptr; - } - - if (synth != nullptr) - { - delete synth; - synth = nullptr; - } - - synth = new SYNTH_T(); - synth->buffersize = host->get_buffer_size(host->handle); - synth->samplerate = host->get_sample_rate(host->handle); - synth->alias(); - - config.init(); - config.cfg.SoundBufferSize = synth->buffersize; - config.cfg.SampleRate = synth->samplerate; - config.cfg.GzipCompression = 0; - - sprng(std::time(nullptr)); - - denormalkillbuf = new float[synth->buffersize]; - for (int i=0; i < synth->buffersize; ++i) - denormalkillbuf[i] = (RND - 0.5f) * 1e-16; - - Master::getInstance(); - } - - void maybeReinit(const HostDescriptor* const host) - { - if (host->get_buffer_size(host->handle) == static_cast(synth->buffersize) && - host->get_sample_rate(host->handle) == static_cast(synth->samplerate)) - return; - - reinit(host); - } - -private: - int fCount; - - CARLA_DECLARE_NON_COPY_CLASS(ZynAddSubFxInstanceCount) -}; - -static ZynAddSubFxInstanceCount sInstanceCount; - -// ----------------------------------------------------------------------- - -class ZynAddSubFxThread : public juce::Thread -{ -public: - ZynAddSubFxThread(Master* const master, const HostDescriptor* const host) - : juce::Thread("ZynAddSubFxThread"), - fMaster(master), - kHost(host), -#ifdef WANT_ZYNADDSUBFX_UI - fUi(nullptr), - fUiClosed(0), - fNextUiAction(-1), -#endif - fChangeProgram(false), - fNextChannel(0), - fNextBank(0), - fNextProgram(0) - { - } - - ~ZynAddSubFxThread() - { -#ifdef WANT_ZYNADDSUBFX_UI - // must be closed by now - CARLA_ASSERT(fUi == nullptr); -#endif - } - - void loadProgramLater(const uint8_t channel, const uint32_t bank, const uint32_t program) - { - fNextChannel = channel; - fNextBank = bank; - fNextProgram = program; - fChangeProgram = true; - } - - void stopLoadProgramLater() - { - fChangeProgram = false; - fNextChannel = 0; - fNextBank = 0; - fNextProgram = 0; - } - - void setMaster(Master* const master) - { - fMaster = master; - } - -#ifdef WANT_ZYNADDSUBFX_UI - void uiHide() - { - fNextUiAction = 0; - } - - void uiShow() - { - fNextUiAction = 1; - } - - void uiRepaint() - { - if (fUi != nullptr) - fNextUiAction = 2; - } -#endif - -protected: - void run() override - { - while (! threadShouldExit()) - { -#ifdef WANT_ZYNADDSUBFX_UI - Fl::lock(); - - if (fNextUiAction == 2) // repaint - { - CARLA_ASSERT(fUi != nullptr); - - if (fUi != nullptr) - fUi->refresh_master_ui(); - } - else if (fNextUiAction == 1) // init/show - { - static bool initialized = false; - - if (! initialized) - { - initialized = true; - fl_register_images(); - - Fl_Dial::default_style(Fl_Dial::PIXMAP_DIAL); - - if (Fl_Shared_Image* const img = Fl_Shared_Image::get(gPixmapPath + "knob.png")) - Fl_Dial::default_image(img); - - if (Fl_Shared_Image* const img = Fl_Shared_Image::get(gPixmapPath + "window_backdrop.png")) - Fl::scheme_bg(new Fl_Tiled_Image(img)); - - if(Fl_Shared_Image* const img = Fl_Shared_Image::get(gPixmapPath + "module_backdrop.png")) - gModuleBackdrop = new Fl_Tiled_Image(img); - - Fl::background(50, 50, 50); - Fl::background2(70, 70, 70); - Fl::foreground(255, 255, 255); - - Fl_Theme::set("Cairo"); - } - - CARLA_ASSERT(fUi == nullptr); - - if (fUi == nullptr) - { - fUiClosed = 0; - fUi = new MasterUI(fMaster, &fUiClosed); - fUi->masterwindow->label(kHost->uiName); - fUi->showUI(); - } - } - else if (fNextUiAction == 0) // close - { - CARLA_ASSERT(fUi != nullptr); - - if (fUi != nullptr) - { - delete fUi; - fUi = nullptr; - } - } - - fNextUiAction = -1; - - if (fUiClosed != 0) - { - fUiClosed = 0; - fNextUiAction = 0; - kHost->ui_closed(kHost->handle); - } - - Fl::check(); - Fl::unlock(); -#endif - - if (fChangeProgram) - { - fChangeProgram = false; - sPrograms.load(fMaster, fNextChannel, fNextBank, fNextProgram); - fNextChannel = 0; - fNextBank = 0; - fNextProgram = 0; - -#ifdef WANT_ZYNADDSUBFX_UI - if (fUi != nullptr) - { - Fl::lock(); - fUi->refresh_master_ui(); - Fl::unlock(); - } -#endif - - carla_msleep(15); - } - else - { - carla_msleep(30); - } - } - -#ifdef WANT_ZYNADDSUBFX_UI - if (threadShouldExit() && fUi != nullptr) - { - Fl::lock(); - delete fUi; - fUi = nullptr; - Fl::check(); - Fl::unlock(); - } -#endif - } - -private: - Master* fMaster; - const HostDescriptor* const kHost; - -#ifdef WANT_ZYNADDSUBFX_UI - MasterUI* fUi; - int fUiClosed; - volatile int fNextUiAction; -#endif - - volatile bool fChangeProgram; - volatile uint8_t fNextChannel; - volatile uint32_t fNextBank; - volatile uint32_t fNextProgram; -}; - -// ----------------------------------------------------------------------- - -#define ZynPluginClassEND(ClassName) \ -public: \ - static PluginHandle _instantiate(const HostDescriptor* host) \ - { \ - sInstanceCount.addOne(host); \ - return new ClassName(host); \ - } \ - static void _cleanup(PluginHandle handle) \ - { \ - delete (ClassName*)handle; \ - sInstanceCount.removeOne(); \ - } - // ----------------------------------------------------------------------- class FxAbstractPlugin : public PluginClass @@ -572,21 +32,22 @@ class FxAbstractPlugin : public PluginClass protected: FxAbstractPlugin(const HostDescriptor* const host, const uint32_t paramCount, const uint32_t programCount) : PluginClass(host), + fParamCount(paramCount-2), // volume and pan handled by host + fProgramCount(programCount), fEffect(nullptr), - efxoutl(new float[synth->buffersize]), - efxoutr(new float[synth->buffersize]), - fFirstInit(true), - kParamCount(paramCount-2), // volume and pan handled by host - kProgramCount(programCount) + efxoutl(nullptr), + efxoutr(nullptr), + fFirstInit(true) { - carla_zeroFloat(efxoutl, synth->buffersize); - carla_zeroFloat(efxoutr, synth->buffersize); + const uint32_t bufferSize(getBufferSize()); + efxoutl = new float[bufferSize]; + efxoutr = new float[bufferSize]; + carla_zeroFloat(efxoutl, bufferSize); + carla_zeroFloat(efxoutr, bufferSize); } ~FxAbstractPlugin() override { - CARLA_ASSERT(fEffect != nullptr); - if (efxoutl != nullptr) { delete[] efxoutl; @@ -611,7 +72,7 @@ protected: uint32_t getParameterCount() const final { - return kParamCount; + return fParamCount; } float getParameterValue(const uint32_t index) const final @@ -624,7 +85,7 @@ protected: uint32_t getMidiProgramCount() const final { - return kProgramCount; + return fProgramCount; } // ------------------------------------------------------------------- @@ -632,12 +93,13 @@ protected: void setParameterValue(const uint32_t index, const float value) final { - fEffect->changepar(index+2, value); fFirstInit = false; + fEffect->changepar(index+2, value); } void setMidiProgram(const uint8_t, const uint32_t, const uint32_t program) final { + fFirstInit = false; fEffect->setpreset(program); const float volume(float(fEffect->getpar(0))/127.0f); @@ -667,8 +129,6 @@ protected: void process(float** const inBuffer, float** const outBuffer, const uint32_t frames, const MidiEvent* const, const uint32_t) final { - CARLA_ASSERT(synth->buffersize == static_cast(frames)); - fEffect->out(Stereo(inBuffer[0], inBuffer[1])); carla_copyFloat(outBuffer[0], efxoutl, frames); @@ -684,25 +144,41 @@ protected: delete[] efxoutr; efxoutl = new float[bufferSize]; efxoutr = new float[bufferSize]; - carla_zeroFloat(efxoutl, synth->buffersize); - carla_zeroFloat(efxoutr, synth->buffersize); - *((float**)&fEffect->efxoutl) = efxoutl; - *((float**)&fEffect->efxoutr) = efxoutr; + carla_zeroFloat(efxoutl, bufferSize); + carla_zeroFloat(efxoutr, bufferSize); - sInstanceCount.maybeReinit(getHostHandle()); + doReinit(bufferSize, getSampleRate()); } - void sampleRateChanged(const double) final + void sampleRateChanged(const double sampleRate) final { - sInstanceCount.maybeReinit(getHostHandle()); + doReinit(getBufferSize(), sampleRate); + } + + void doReinit(const uint32_t bufferSize, const double sampleRate) + { + float params[fParamCount]; + + for (uint32_t i=0; i < fParamCount; ++i) + params[i] = fEffect->getpar(i+2); + + reinit(bufferSize, sampleRate); + + for (uint32_t i=0; i < fParamCount; ++i) + fEffect->changepar(i+2, params[i]); } + virtual void reinit(const uint32_t bufferSize, const double sampleRate) = 0; + + // ------------------------------------------------------------------- + + const uint32_t fParamCount; + const uint32_t fProgramCount; + Effect* fEffect; float* efxoutl; float* efxoutr; bool fFirstInit; - const uint32_t kParamCount; - const uint32_t kProgramCount; }; // ----------------------------------------------------------------------- @@ -713,7 +189,7 @@ public: FxAlienWahPlugin(const HostDescriptor* const host) : FxAbstractPlugin(host, 11, 4) { - fEffect = new Alienwah(false, efxoutl, efxoutr); + fEffect = new Alienwah(false, efxoutl, efxoutr, getSampleRate(), getBufferSize()); } protected: @@ -722,7 +198,7 @@ protected: const Parameter* getParameterInfo(const uint32_t index) const override { - if (index >= kParamCount) + if (index >= fParamCount) return nullptr; static Parameter param; @@ -808,7 +284,7 @@ protected: const MidiProgram* getMidiProgramInfo(const uint32_t index) const override { - if (index >= kProgramCount) + if (index >= fProgramCount) return nullptr; static MidiProgram midiProg; @@ -838,7 +314,15 @@ protected: return &midiProg; } - ZynPluginClassEND(FxAlienWahPlugin) + // ------------------------------------------------------------------- + + void reinit(const uint32_t bufferSize, const double sampleRate) + { + delete fEffect; + fEffect = new Alienwah(false, efxoutl, efxoutr, sampleRate, bufferSize); + } + + PluginClassEND(FxAlienWahPlugin) CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(FxAlienWahPlugin) }; @@ -850,7 +334,7 @@ public: FxChorusPlugin(const HostDescriptor* const host) : FxAbstractPlugin(host, 12, 10) { - fEffect = new Chorus(false, efxoutl, efxoutr); + fEffect = new Chorus(false, efxoutl, efxoutr, getSampleRate(), getBufferSize()); } protected: @@ -859,7 +343,7 @@ protected: const Parameter* getParameterInfo(const uint32_t index) const override { - if (index >= kParamCount) + if (index >= fParamCount) return nullptr; static Parameter param; @@ -951,7 +435,7 @@ protected: const MidiProgram* getMidiProgramInfo(const uint32_t index) const override { - if (index >= kProgramCount) + if (index >= fProgramCount) return nullptr; static MidiProgram midiProg; @@ -999,7 +483,15 @@ protected: return &midiProg; } - ZynPluginClassEND(FxChorusPlugin) + // ------------------------------------------------------------------- + + void reinit(const uint32_t bufferSize, const double sampleRate) + { + delete fEffect; + fEffect = new Chorus(false, efxoutl, efxoutr, sampleRate, bufferSize); + } + + PluginClassEND(FxChorusPlugin) CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(FxChorusPlugin) }; @@ -1011,7 +503,7 @@ public: FxDistortionPlugin(const HostDescriptor* const host) : FxAbstractPlugin(host, 11, 6) { - fEffect = new Distorsion(false, efxoutl, efxoutr); + fEffect = new Distorsion(false, efxoutl, efxoutr, getSampleRate(), getBufferSize()); } protected: @@ -1020,7 +512,7 @@ protected: const Parameter* getParameterInfo(const uint32_t index) const override { - if (index >= kParamCount) + if (index >= fParamCount) return nullptr; static Parameter param; @@ -1132,7 +624,7 @@ protected: const MidiProgram* getMidiProgramInfo(const uint32_t index) const override { - if (index >= kProgramCount) + if (index >= fProgramCount) return nullptr; static MidiProgram midiProg; @@ -1168,7 +660,15 @@ protected: return &midiProg; } - ZynPluginClassEND(FxDistortionPlugin) + // ------------------------------------------------------------------- + + void reinit(const uint32_t bufferSize, const double sampleRate) + { + delete fEffect; + fEffect = new Distorsion(false, efxoutl, efxoutr, sampleRate, bufferSize); + } + + PluginClassEND(FxDistortionPlugin) CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(FxDistortionPlugin) }; @@ -1180,7 +680,7 @@ public: FxDynamicFilterPlugin(const HostDescriptor* const host) : FxAbstractPlugin(host, 10, 5) { - fEffect = new DynamicFilter(false, efxoutl, efxoutr); + fEffect = new DynamicFilter(false, efxoutl, efxoutr, getSampleRate(), getBufferSize()); } protected: @@ -1189,7 +689,7 @@ protected: const Parameter* getParameterInfo(const uint32_t index) const override { - if (index >= kParamCount) + if (index >= fParamCount) return nullptr; static Parameter param; @@ -1270,7 +770,7 @@ protected: const MidiProgram* getMidiProgramInfo(const uint32_t index) const override { - if (index >= kProgramCount) + if (index >= fProgramCount) return nullptr; static MidiProgram midiProg; @@ -1303,7 +803,15 @@ protected: return &midiProg; } - ZynPluginClassEND(FxDynamicFilterPlugin) + // ------------------------------------------------------------------- + + void reinit(const uint32_t bufferSize, const double sampleRate) + { + delete fEffect; + fEffect = new DynamicFilter(false, efxoutl, efxoutr, sampleRate, bufferSize); + } + + PluginClassEND(FxDynamicFilterPlugin) CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(FxDynamicFilterPlugin) }; @@ -1315,7 +823,7 @@ public: FxEchoPlugin(const HostDescriptor* const host) : FxAbstractPlugin(host, 7, 9) { - fEffect = new Echo(false, efxoutl, efxoutr); + fEffect = new Echo(false, efxoutl, efxoutr, getSampleRate(), getBufferSize()); } protected: @@ -1324,7 +832,7 @@ protected: const Parameter* getParameterInfo(const uint32_t index) const override { - if (index >= kParamCount) + if (index >= fParamCount) return nullptr; static Parameter param; @@ -1381,7 +889,7 @@ protected: const MidiProgram* getMidiProgramInfo(const uint32_t index) const override { - if (index >= kProgramCount) + if (index >= fProgramCount) return nullptr; static MidiProgram midiProg; @@ -1426,7 +934,15 @@ protected: return &midiProg; } - ZynPluginClassEND(FxEchoPlugin) + // ------------------------------------------------------------------- + + void reinit(const uint32_t bufferSize, const double sampleRate) + { + delete fEffect; + fEffect = new Echo(false, efxoutl, efxoutr, sampleRate, bufferSize); + } + + PluginClassEND(FxEchoPlugin) CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(FxEchoPlugin) }; @@ -1438,7 +954,7 @@ public: FxPhaserPlugin(const HostDescriptor* const host) : FxAbstractPlugin(host, 15, 12) { - fEffect = new Phaser(false, efxoutl, efxoutr); + fEffect = new Phaser(false, efxoutl, efxoutr, getSampleRate(), getBufferSize()); } protected: @@ -1447,7 +963,7 @@ protected: const Parameter* getParameterInfo(const uint32_t index) const override { - if (index >= kParamCount) + if (index >= fParamCount) return nullptr; static Parameter param; @@ -1556,7 +1072,7 @@ protected: const MidiProgram* getMidiProgramInfo(const uint32_t index) const override { - if (index >= kProgramCount) + if (index >= fProgramCount) return nullptr; static MidiProgram midiProg; @@ -1610,7 +1126,15 @@ protected: return &midiProg; } - ZynPluginClassEND(FxPhaserPlugin) + // ------------------------------------------------------------------- + + void reinit(const uint32_t bufferSize, const double sampleRate) + { + delete fEffect; + fEffect = new Phaser(false, efxoutl, efxoutr, sampleRate, bufferSize); + } + + PluginClassEND(FxPhaserPlugin) CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(FxPhaserPlugin) }; @@ -1622,7 +1146,7 @@ public: FxReverbPlugin(const HostDescriptor* const host) : FxAbstractPlugin(host, 13, 13) { - fEffect = new Reverb(false, efxoutl, efxoutr); + fEffect = new Reverb(false, efxoutl, efxoutr, getSampleRate(), getBufferSize()); } protected: @@ -1631,7 +1155,7 @@ protected: const Parameter* getParameterInfo(const uint32_t index) const override { - if (index >= kParamCount) + if (index >= fParamCount) return nullptr; static Parameter param; @@ -1723,7 +1247,7 @@ protected: const MidiProgram* getMidiProgramInfo(const uint32_t index) const override { - if (index >= kProgramCount) + if (index >= fProgramCount) return nullptr; static MidiProgram midiProg; @@ -1780,235 +1304,16 @@ protected: return &midiProg; } - ZynPluginClassEND(FxReverbPlugin) - CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(FxReverbPlugin) -}; - -// ----------------------------------------------------------------------- - -class ZynAddSubFxPlugin : public PluginClass -{ -public: - ZynAddSubFxPlugin(const HostDescriptor* const host) - : PluginClass(host), - fMaster(new Master()), - fSampleRate(getSampleRate()), - fIsActive(false), - fThread(fMaster, host) - { - fThread.startThread(3); - - for (int i = 0; i < NUM_MIDI_PARTS; ++i) - fMaster->partonoff(i, 1); - - sPrograms.init(); - } - - ~ZynAddSubFxPlugin() override - { - //ensure that everything has stopped - pthread_mutex_lock(&fMaster->mutex); - pthread_mutex_unlock(&fMaster->mutex); - fThread.stopThread(-1); - - delete fMaster; - fMaster = nullptr; - } - -protected: - // ------------------------------------------------------------------- - // Plugin midi-program calls - - uint32_t getMidiProgramCount() const override - { - return sPrograms.count(); - } - - const MidiProgram* getMidiProgramInfo(const uint32_t index) const override - { - return sPrograms.getInfo(index); - } - - // ------------------------------------------------------------------- - // Plugin state calls - - void setMidiProgram(const uint8_t channel, const uint32_t bank, const uint32_t program) override - { - if (bank >= fMaster->bank.banks.size()) - return; - if (program >= BANK_SIZE) - return; - - if (isOffline() || ! fIsActive) - { - sPrograms.load(fMaster, channel, bank, program); -#ifdef WANT_ZYNADDSUBFX_UI - fThread.uiRepaint(); -#endif - } - else - fThread.loadProgramLater(channel, bank, program); - } - - void setCustomData(const char* const key, const char* const value) override - { - CARLA_ASSERT(key != nullptr); - CARLA_ASSERT(value != nullptr); - - if (std::strcmp(key, "CarlaAlternateFile1") == 0) // xmz - fMaster->loadXML(value); - else if (std::strcmp(key, "CarlaAlternateFile2") == 0) // xiz - fMaster->part[0]->loadXMLinstrument(value); - } - - // ------------------------------------------------------------------- - // Plugin process calls - - void activate() override - { - fIsActive = true; - } - - void deactivate() override - { - fIsActive = false; - } - - void process(float**, float** const outBuffer, const uint32_t frames, const MidiEvent* const midiEvents, const uint32_t midiEventCount) override - { - if (pthread_mutex_trylock(&fMaster->mutex) != 0) - { - carla_zeroFloat(outBuffer[0], frames); - carla_zeroFloat(outBuffer[1], frames); - return; - } - - for (uint32_t i=0; i < midiEventCount; ++i) - { - const MidiEvent* const midiEvent(&midiEvents[i]); - - const uint8_t status = MIDI_GET_STATUS_FROM_DATA(midiEvent->data); - const uint8_t channel = MIDI_GET_CHANNEL_FROM_DATA(midiEvent->data); - - if (MIDI_IS_STATUS_NOTE_OFF(status)) - { - const uint8_t note = midiEvent->data[1]; - - fMaster->noteOff(channel, note); - } - else if (MIDI_IS_STATUS_NOTE_ON(status)) - { - const uint8_t note = midiEvent->data[1]; - const uint8_t velo = midiEvent->data[2]; - - fMaster->noteOn(channel, note, velo); - } - else if (MIDI_IS_STATUS_POLYPHONIC_AFTERTOUCH(status)) - { - const uint8_t note = midiEvent->data[1]; - const uint8_t pressure = midiEvent->data[2]; - - fMaster->polyphonicAftertouch(channel, note, pressure); - } - else if (MIDI_IS_STATUS_CONTROL_CHANGE(status)) - { - const uint8_t control = midiEvent->data[1]; - const uint8_t value = midiEvent->data[2]; - - fMaster->setController(channel, control, value); - } - else if (MIDI_IS_STATUS_PITCH_WHEEL_CONTROL(status)) - { - const uint8_t lsb = midiEvent->data[1]; - const uint8_t msb = midiEvent->data[2]; - const int value = ((msb << 7) | lsb) - 8192; - - fMaster->setController(channel, C_pitchwheel, value); - } - } - - fMaster->GetAudioOutSamples(frames, fSampleRate, outBuffer[0], outBuffer[1]); - - pthread_mutex_unlock(&fMaster->mutex); - } - -#ifdef WANT_ZYNADDSUBFX_UI - // ------------------------------------------------------------------- - // Plugin UI calls - - void uiShow(const bool show) override - { - if (show) - fThread.uiShow(); - else - fThread.uiHide(); - } -#endif - // ------------------------------------------------------------------- - // Plugin state calls - char* getState() const override + void reinit(const uint32_t bufferSize, const double sampleRate) { - config.save(); - - char* data = nullptr; - fMaster->getalldata(&data); - return data; - } - - void setState(const char* const data) override - { - fThread.stopLoadProgramLater(); - fMaster->putalldata((char*)data, 0); - fMaster->applyparameters(true); - } - -#if 0 - // ------------------------------------------------------------------- - // Plugin dispatcher - - intptr_t pluginDispatcher(const PluginDispatcherOpcode opcode, const int32_t index, const intptr_t value, void* const ptr, const float) override - { - switch (opcode) - { - case PLUGIN_OPCODE_NULL: - break; - case PLUGIN_OPCODE_BUFFER_SIZE_CHANGED: - // TODO - break; - case PLUGIN_OPCODE_SAMPLE_RATE_CHANGED: - // TODO - break; - case PLUGIN_OPCODE_OFFLINE_CHANGED: - break; - case PLUGIN_OPCODE_UI_NAME_CHANGED: -#ifdef WANT_ZYNADDSUBFX_UI - // TODO -#endif - break; - } - - return 0; - - // unused - (void)index; - (void)value; - (void)ptr; + delete fEffect; + fEffect = new Reverb(false, efxoutl, efxoutr, sampleRate, bufferSize); } -#endif - - // ------------------------------------------------------------------- - -private: - Master* fMaster; - unsigned fSampleRate; - bool fIsActive; - ZynAddSubFxThread fThread; - - ZynPluginClassEND(ZynAddSubFxPlugin) - CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ZynAddSubFxPlugin) + PluginClassEND(FxReverbPlugin) + CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(FxReverbPlugin) }; // ----------------------------------------------------------------------- @@ -2132,31 +1437,10 @@ static const PluginDescriptor fxReverbDesc = { PluginDescriptorFILL(FxReverbPlugin) }; -static const PluginDescriptor zynaddsubfxDesc = { - /* category */ PLUGIN_CATEGORY_SYNTH, -#ifdef WANT_ZYNADDSUBFX_UI - /* hints */ static_cast(PLUGIN_HAS_GUI|PLUGIN_USES_STATE), -#else - /* hints */ static_cast(PLUGIN_USES_STATE), -#endif - /* supports */ static_cast(PLUGIN_SUPPORTS_CONTROL_CHANGES|PLUGIN_SUPPORTS_NOTE_AFTERTOUCH|PLUGIN_SUPPORTS_PITCHBEND|PLUGIN_SUPPORTS_ALL_SOUND_OFF), - /* audioIns */ 0, - /* audioOuts */ 2, - /* midiIns */ 1, - /* midiOuts */ 0, - /* paramIns */ 0, - /* paramOuts */ 0, - /* name */ "ZynAddSubFX", - /* label */ "zynaddsubfx", - /* maker */ "falkTX", - /* copyright */ "GNU GPL v2+", - PluginDescriptorFILL(ZynAddSubFxPlugin) -}; - // ----------------------------------------------------------------------- CARLA_EXPORT -void carla_register_native_plugin_zynaddsubfx() +void carla_register_native_plugin_zynaddsubfx_fx() { carla_register_native_plugin(&fxAlienWahDesc); carla_register_native_plugin(&fxChorusDesc); @@ -2165,7 +1449,6 @@ void carla_register_native_plugin_zynaddsubfx() carla_register_native_plugin(&fxEchoDesc); carla_register_native_plugin(&fxPhaserDesc); carla_register_native_plugin(&fxReverbDesc); - carla_register_native_plugin(&zynaddsubfxDesc); } // ----------------------------------------------------------------------- diff --git a/source/modules/carla_native/zynaddsubfx-src.cpp b/source/modules/carla_native/zynaddsubfx-src.cpp index e697e42ae..2d16558cb 100644 --- a/source/modules/carla_native/zynaddsubfx-src.cpp +++ b/source/modules/carla_native/zynaddsubfx-src.cpp @@ -63,3 +63,22 @@ #include "zynaddsubfx/Synth/Resonance.cpp" #include "zynaddsubfx/Synth/SUBnote.cpp" #include "zynaddsubfx/Synth/SynthNote.cpp" + +// Dummy variables and functions for linking purposes +const char* instance_name = nullptr; +SYNTH_T* synth = nullptr; +class WavFile; +namespace Nio { + bool start(void){return 1;} + void stop(void){} + bool setSource(std::string){return true;} + bool setSink(std::string){return true;} + std::set getSources(void){return std::set();} + std::set getSinks(void){return std::set();} + std::string getSource(void){return "";} + std::string getSink(void){return "";} + void waveNew(WavFile*){} + void waveStart(void){} + void waveStop(void){} + void waveEnd(void){} +} diff --git a/source/modules/carla_native/zynaddsubfx-synth.cpp b/source/modules/carla_native/zynaddsubfx-synth.cpp new file mode 100644 index 000000000..b89e2ab4c --- /dev/null +++ b/source/modules/carla_native/zynaddsubfx-synth.cpp @@ -0,0 +1,794 @@ +/* + * Carla Native Plugins + * Copyright (C) 2012-2013 Filipe Coelho + * + * This program 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 2 of + * the License, or any later version. + * + * This program 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. + * + * For a full copy of the GNU General Public License see the doc/GPL.txt file. + */ + +// for UINT32_MAX +#define __STDC_LIMIT_MACROS +#include + +#include "CarlaNative.hpp" +#include "CarlaMIDI.h" +#include "CarlaString.hpp" +#include "RtList.hpp" + +#include "zynaddsubfx/Misc/Master.h" +#include "zynaddsubfx/Misc/Part.h" +#include "zynaddsubfx/Misc/Util.h" + +#ifdef WANT_ZYNADDSUBFX_UI +# ifdef override +# define override_hack +# undef override +# endif + +# include "zynaddsubfx/UI/common.H" +# include "zynaddsubfx/UI/MasterUI.h" +# include +# include +# include + +# ifdef override_hack +# define override +# undef override_hack +# endif +#endif + +#include +#include +#include + +#include "juce_core.h" + +#ifdef WANT_ZYNADDSUBFX_UI + +static Fl_Tiled_Image* gModuleBackdrop = nullptr; +static CarlaString gPixmapPath; +extern CarlaString gUiPixmapPath; + +void set_module_parameters(Fl_Widget* o) +{ + CARLA_ASSERT(gModuleBackdrop != nullptr); + + o->box(FL_DOWN_FRAME); + o->align(o->align() | FL_ALIGN_IMAGE_BACKDROP); + o->color(FL_BLACK); + o->labeltype(FL_SHADOW_LABEL); + + if (gModuleBackdrop != nullptr) + o->image(gModuleBackdrop); +} +#endif + +// ----------------------------------------------------------------------- + +class ZynAddSubFxPrograms +{ +public: + ZynAddSubFxPrograms() + : fInitiated(false) + { + } + + ~ZynAddSubFxPrograms() + { + if (! fInitiated) + return; + + for (auto it = fPrograms.begin(); it.valid(); it.next()) + { + const ProgramInfo*& pInfo(*it); + delete pInfo; + } + + fPrograms.clear(); + } + + void init() + { + if (fInitiated) + return; + fInitiated = true; + + fPrograms.append(new ProgramInfo(0, 0, "default")); + + Master& master(Master::getInstance()); + + pthread_mutex_lock(&master.mutex); + + // refresh banks + master.bank.rescanforbanks(); + + for (uint32_t i=0, size = master.bank.banks.size(); i < size; ++i) + { + if (master.bank.banks[i].dir.empty()) + continue; + + master.bank.loadbank(master.bank.banks[i].dir); + + for (unsigned int instrument = 0; instrument < BANK_SIZE; ++instrument) + { + const std::string insName(master.bank.getname(instrument)); + + if (insName.empty() || insName[0] == '\0' || insName[0] == ' ') + continue; + + fPrograms.append(new ProgramInfo(i+1, instrument, insName.c_str())); + } + } + + pthread_mutex_unlock(&master.mutex); + } + + void load(Master* const master, const uint8_t channel, const uint32_t bank, const uint32_t program) + { + if (bank == 0) + { + pthread_mutex_lock(&master->mutex); + + master->partonoff(channel, 1); + master->part[channel]->defaults(); + master->part[channel]->applyparameters(false); + + pthread_mutex_unlock(&master->mutex); + + return; + } + + const std::string& bankdir(master->bank.banks[bank-1].dir); + + if (! bankdir.empty()) + { + pthread_mutex_lock(&master->mutex); + + master->partonoff(channel, 1); + + master->bank.loadbank(bankdir); + master->bank.loadfromslot(program, master->part[channel]); + + master->part[channel]->applyparameters(false); + + pthread_mutex_unlock(&master->mutex); + } + } + + uint32_t count() + { + return fPrograms.count(); + } + + const MidiProgram* getInfo(const uint32_t index) + { + if (index >= fPrograms.count()) + return nullptr; + + const ProgramInfo*& pInfo(fPrograms.getAt(index)); + + fRetProgram.bank = pInfo->bank; + fRetProgram.program = pInfo->prog; + fRetProgram.name = pInfo->name; + + return &fRetProgram; + } + +private: + struct ProgramInfo { + uint32_t bank; + uint32_t prog; + const char* name; + + ProgramInfo(uint32_t bank_, uint32_t prog_, const char* name_) + : bank(bank_), + prog(prog_), + name(carla_strdup(name_)) {} + + ~ProgramInfo() + { + if (name != nullptr) + { + delete[] name; + name = nullptr; + } + } + +#ifdef CARLA_PROPER_CPP11_SUPPORT + ProgramInfo() = delete; + ProgramInfo(ProgramInfo&) = delete; + ProgramInfo(const ProgramInfo&) = delete; + ProgramInfo& operator=(ProgramInfo&); + ProgramInfo& operator=(const ProgramInfo&); +#endif + }; + + bool fInitiated; + MidiProgram fRetProgram; + NonRtList fPrograms; + + CARLA_DECLARE_NON_COPY_CLASS(ZynAddSubFxPrograms) +}; + +static ZynAddSubFxPrograms sPrograms; + +// ----------------------------------------------------------------------- + +class ZynAddSubFxInstanceCount +{ +public: + ZynAddSubFxInstanceCount() + : fCount(0) + { + } + + ~ZynAddSubFxInstanceCount() + { + CARLA_ASSERT(fCount == 0); + } + + void addOne(const HostDescriptor* const host) + { + if (fCount++ == 0) + { + CARLA_ASSERT(synth == nullptr); + CARLA_ASSERT(denormalkillbuf == nullptr); + + reinit(host); + +#ifdef WANT_ZYNADDSUBFX_UI + if (gPixmapPath.isEmpty()) + { + gPixmapPath = host->resourceDir; + gPixmapPath += "/zynaddsubfx/"; + gUiPixmapPath = gPixmapPath; + } +#endif + } + } + + void removeOne() + { + if (--fCount == 0) + { + CARLA_ASSERT(synth != nullptr); + CARLA_ASSERT(denormalkillbuf != nullptr); + + Master::deleteInstance(); + + delete[] denormalkillbuf; + denormalkillbuf = nullptr; + + delete synth; + synth = nullptr; + } + } + + void reinit(const HostDescriptor* const host) + { + Master::deleteInstance(); + + if (denormalkillbuf != nullptr) + { + delete[] denormalkillbuf; + denormalkillbuf = nullptr; + } + + if (synth != nullptr) + { + delete synth; + synth = nullptr; + } + + synth = new SYNTH_T(); + synth->buffersize = host->get_buffer_size(host->handle); + synth->samplerate = host->get_sample_rate(host->handle); + synth->alias(); + + config.init(); + config.cfg.SoundBufferSize = synth->buffersize; + config.cfg.SampleRate = synth->samplerate; + config.cfg.GzipCompression = 0; + + sprng(std::time(nullptr)); + + denormalkillbuf = new float[synth->buffersize]; + for (int i=0; i < synth->buffersize; ++i) + denormalkillbuf[i] = (RND - 0.5f) * 1e-16; + + Master::getInstance(); + } + + void maybeReinit(const HostDescriptor* const host) + { + if (host->get_buffer_size(host->handle) == static_cast(synth->buffersize) && + host->get_sample_rate(host->handle) == static_cast(synth->samplerate)) + return; + + reinit(host); + } + +private: + int fCount; + + CARLA_DECLARE_NON_COPY_CLASS(ZynAddSubFxInstanceCount) +}; + +static ZynAddSubFxInstanceCount sInstanceCount; + +// ----------------------------------------------------------------------- + +class ZynAddSubFxThread : public juce::Thread +{ +public: + ZynAddSubFxThread(Master* const master, const HostDescriptor* const host) + : juce::Thread("ZynAddSubFxThread"), + fMaster(master), + kHost(host), +#ifdef WANT_ZYNADDSUBFX_UI + fUi(nullptr), + fUiClosed(0), + fNextUiAction(-1), +#endif + fChangeProgram(false), + fNextChannel(0), + fNextBank(0), + fNextProgram(0) + { + } + + ~ZynAddSubFxThread() + { +#ifdef WANT_ZYNADDSUBFX_UI + // must be closed by now + CARLA_ASSERT(fUi == nullptr); +#endif + } + + void loadProgramLater(const uint8_t channel, const uint32_t bank, const uint32_t program) + { + fNextChannel = channel; + fNextBank = bank; + fNextProgram = program; + fChangeProgram = true; + } + + void stopLoadProgramLater() + { + fChangeProgram = false; + fNextChannel = 0; + fNextBank = 0; + fNextProgram = 0; + } + + void setMaster(Master* const master) + { + fMaster = master; + } + +#ifdef WANT_ZYNADDSUBFX_UI + void uiHide() + { + fNextUiAction = 0; + } + + void uiShow() + { + fNextUiAction = 1; + } + + void uiRepaint() + { + if (fUi != nullptr) + fNextUiAction = 2; + } +#endif + +protected: + void run() override + { + while (! threadShouldExit()) + { +#ifdef WANT_ZYNADDSUBFX_UI + Fl::lock(); + + if (fNextUiAction == 2) // repaint + { + CARLA_ASSERT(fUi != nullptr); + + if (fUi != nullptr) + fUi->refresh_master_ui(); + } + else if (fNextUiAction == 1) // init/show + { + static bool initialized = false; + + if (! initialized) + { + initialized = true; + fl_register_images(); + + Fl_Dial::default_style(Fl_Dial::PIXMAP_DIAL); + + if (Fl_Shared_Image* const img = Fl_Shared_Image::get(gPixmapPath + "knob.png")) + Fl_Dial::default_image(img); + + if (Fl_Shared_Image* const img = Fl_Shared_Image::get(gPixmapPath + "window_backdrop.png")) + Fl::scheme_bg(new Fl_Tiled_Image(img)); + + if(Fl_Shared_Image* const img = Fl_Shared_Image::get(gPixmapPath + "module_backdrop.png")) + gModuleBackdrop = new Fl_Tiled_Image(img); + + Fl::background(50, 50, 50); + Fl::background2(70, 70, 70); + Fl::foreground(255, 255, 255); + + Fl_Theme::set("Cairo"); + } + + CARLA_ASSERT(fUi == nullptr); + + if (fUi == nullptr) + { + fUiClosed = 0; + fUi = new MasterUI(fMaster, &fUiClosed); + fUi->masterwindow->label(kHost->uiName); + fUi->showUI(); + } + } + else if (fNextUiAction == 0) // close + { + CARLA_ASSERT(fUi != nullptr); + + if (fUi != nullptr) + { + delete fUi; + fUi = nullptr; + } + } + + fNextUiAction = -1; + + if (fUiClosed != 0) + { + fUiClosed = 0; + fNextUiAction = 0; + kHost->ui_closed(kHost->handle); + } + + Fl::check(); + Fl::unlock(); +#endif + + if (fChangeProgram) + { + fChangeProgram = false; + sPrograms.load(fMaster, fNextChannel, fNextBank, fNextProgram); + fNextChannel = 0; + fNextBank = 0; + fNextProgram = 0; + +#ifdef WANT_ZYNADDSUBFX_UI + if (fUi != nullptr) + { + Fl::lock(); + fUi->refresh_master_ui(); + Fl::unlock(); + } +#endif + + carla_msleep(15); + } + else + { + carla_msleep(30); + } + } + +#ifdef WANT_ZYNADDSUBFX_UI + if (threadShouldExit() && fUi != nullptr) + { + Fl::lock(); + delete fUi; + fUi = nullptr; + Fl::check(); + Fl::unlock(); + } +#endif + } + +private: + Master* fMaster; + const HostDescriptor* const kHost; + +#ifdef WANT_ZYNADDSUBFX_UI + MasterUI* fUi; + int fUiClosed; + volatile int fNextUiAction; +#endif + + volatile bool fChangeProgram; + volatile uint8_t fNextChannel; + volatile uint32_t fNextBank; + volatile uint32_t fNextProgram; +}; + +// ----------------------------------------------------------------------- + +class ZynAddSubFxPlugin : public PluginClass +{ +public: + ZynAddSubFxPlugin(const HostDescriptor* const host) + : PluginClass(host), + fMaster(new Master()), + fSampleRate(getSampleRate()), + fIsActive(false), + fThread(fMaster, host) + { + fThread.startThread(3); + + for (int i = 0; i < NUM_MIDI_PARTS; ++i) + fMaster->partonoff(i, 1); + + sPrograms.init(); + } + + ~ZynAddSubFxPlugin() override + { + //ensure that everything has stopped + pthread_mutex_lock(&fMaster->mutex); + pthread_mutex_unlock(&fMaster->mutex); + fThread.stopThread(-1); + + delete fMaster; + fMaster = nullptr; + } + +protected: + // ------------------------------------------------------------------- + // Plugin midi-program calls + + uint32_t getMidiProgramCount() const override + { + return sPrograms.count(); + } + + const MidiProgram* getMidiProgramInfo(const uint32_t index) const override + { + return sPrograms.getInfo(index); + } + + // ------------------------------------------------------------------- + // Plugin state calls + + void setMidiProgram(const uint8_t channel, const uint32_t bank, const uint32_t program) override + { + if (bank >= fMaster->bank.banks.size()) + return; + if (program >= BANK_SIZE) + return; + + if (isOffline() || ! fIsActive) + { + sPrograms.load(fMaster, channel, bank, program); +#ifdef WANT_ZYNADDSUBFX_UI + fThread.uiRepaint(); +#endif + } + else + fThread.loadProgramLater(channel, bank, program); + } + + void setCustomData(const char* const key, const char* const value) override + { + CARLA_ASSERT(key != nullptr); + CARLA_ASSERT(value != nullptr); + + if (std::strcmp(key, "CarlaAlternateFile1") == 0) // xmz + fMaster->loadXML(value); + else if (std::strcmp(key, "CarlaAlternateFile2") == 0) // xiz + fMaster->part[0]->loadXMLinstrument(value); + } + + // ------------------------------------------------------------------- + // Plugin process calls + + void activate() override + { + fIsActive = true; + } + + void deactivate() override + { + fIsActive = false; + } + + void process(float**, float** const outBuffer, const uint32_t frames, const MidiEvent* const midiEvents, const uint32_t midiEventCount) override + { + if (pthread_mutex_trylock(&fMaster->mutex) != 0) + { + carla_zeroFloat(outBuffer[0], frames); + carla_zeroFloat(outBuffer[1], frames); + return; + } + + for (uint32_t i=0; i < midiEventCount; ++i) + { + const MidiEvent* const midiEvent(&midiEvents[i]); + + const uint8_t status = MIDI_GET_STATUS_FROM_DATA(midiEvent->data); + const uint8_t channel = MIDI_GET_CHANNEL_FROM_DATA(midiEvent->data); + + if (MIDI_IS_STATUS_NOTE_OFF(status)) + { + const uint8_t note = midiEvent->data[1]; + + fMaster->noteOff(channel, note); + } + else if (MIDI_IS_STATUS_NOTE_ON(status)) + { + const uint8_t note = midiEvent->data[1]; + const uint8_t velo = midiEvent->data[2]; + + fMaster->noteOn(channel, note, velo); + } + else if (MIDI_IS_STATUS_POLYPHONIC_AFTERTOUCH(status)) + { + const uint8_t note = midiEvent->data[1]; + const uint8_t pressure = midiEvent->data[2]; + + fMaster->polyphonicAftertouch(channel, note, pressure); + } + else if (MIDI_IS_STATUS_CONTROL_CHANGE(status)) + { + const uint8_t control = midiEvent->data[1]; + const uint8_t value = midiEvent->data[2]; + + fMaster->setController(channel, control, value); + } + else if (MIDI_IS_STATUS_PITCH_WHEEL_CONTROL(status)) + { + const uint8_t lsb = midiEvent->data[1]; + const uint8_t msb = midiEvent->data[2]; + const int value = ((msb << 7) | lsb) - 8192; + + fMaster->setController(channel, C_pitchwheel, value); + } + } + + fMaster->GetAudioOutSamples(frames, fSampleRate, outBuffer[0], outBuffer[1]); + + pthread_mutex_unlock(&fMaster->mutex); + } + +#ifdef WANT_ZYNADDSUBFX_UI + // ------------------------------------------------------------------- + // Plugin UI calls + + void uiShow(const bool show) override + { + if (show) + fThread.uiShow(); + else + fThread.uiHide(); + } +#endif + + // ------------------------------------------------------------------- + // Plugin state calls + + char* getState() const override + { + config.save(); + + char* data = nullptr; + fMaster->getalldata(&data); + return data; + } + + void setState(const char* const data) override + { + fThread.stopLoadProgramLater(); + fMaster->putalldata((char*)data, 0); + fMaster->applyparameters(true); + } + +#if 0 + // ------------------------------------------------------------------- + // Plugin dispatcher + + intptr_t pluginDispatcher(const PluginDispatcherOpcode opcode, const int32_t index, const intptr_t value, void* const ptr, const float) override + { + switch (opcode) + { + case PLUGIN_OPCODE_NULL: + break; + case PLUGIN_OPCODE_BUFFER_SIZE_CHANGED: + // TODO + break; + case PLUGIN_OPCODE_SAMPLE_RATE_CHANGED: + // TODO + break; + case PLUGIN_OPCODE_OFFLINE_CHANGED: + break; + case PLUGIN_OPCODE_UI_NAME_CHANGED: +#ifdef WANT_ZYNADDSUBFX_UI + // TODO +#endif + break; + } + + return 0; + + // unused + (void)index; + (void)value; + (void)ptr; + } +#endif + + // ------------------------------------------------------------------- + +private: + Master* fMaster; + unsigned fSampleRate; + bool fIsActive; + + ZynAddSubFxThread fThread; + +public: + static PluginHandle _instantiate(const HostDescriptor* host) + { + sInstanceCount.addOne(host); + return new ZynAddSubFxPlugin(host); + } + static void _cleanup(PluginHandle handle) + { + delete (ZynAddSubFxPlugin*)handle; + sInstanceCount.removeOne(); + } + + CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(ZynAddSubFxPlugin) +}; + +// ----------------------------------------------------------------------- + +static const PluginDescriptor zynaddsubfxDesc = { + /* category */ PLUGIN_CATEGORY_SYNTH, +#ifdef WANT_ZYNADDSUBFX_UI + /* hints */ static_cast(PLUGIN_HAS_GUI|PLUGIN_USES_STATE), +#else + /* hints */ static_cast(PLUGIN_USES_STATE), +#endif + /* supports */ static_cast(PLUGIN_SUPPORTS_CONTROL_CHANGES|PLUGIN_SUPPORTS_NOTE_AFTERTOUCH|PLUGIN_SUPPORTS_PITCHBEND|PLUGIN_SUPPORTS_ALL_SOUND_OFF), + /* audioIns */ 0, + /* audioOuts */ 2, + /* midiIns */ 1, + /* midiOuts */ 0, + /* paramIns */ 0, + /* paramOuts */ 0, + /* name */ "ZynAddSubFX", + /* label */ "zynaddsubfx", + /* maker */ "falkTX", + /* copyright */ "GNU GPL v2+", + PluginDescriptorFILL(ZynAddSubFxPlugin) +}; + +// ----------------------------------------------------------------------- + +CARLA_EXPORT +void carla_register_native_plugin_zynaddsubfx_synth() +{ + carla_register_native_plugin(&zynaddsubfxDesc); +} + +// ----------------------------------------------------------------------- diff --git a/source/modules/carla_native/zynaddsubfx/DSP/AnalogFilter.cpp b/source/modules/carla_native/zynaddsubfx/DSP/AnalogFilter.cpp index e7f7cfec8..0f839dc97 100644 --- a/source/modules/carla_native/zynaddsubfx/DSP/AnalogFilter.cpp +++ b/source/modules/carla_native/zynaddsubfx/DSP/AnalogFilter.cpp @@ -31,14 +31,19 @@ AnalogFilter::AnalogFilter(unsigned char Ftype, float Ffreq, float Fq, - unsigned char Fstages) + unsigned char Fstages, + float srate, int bufsize) :type(Ftype), stages(Fstages), freq(Ffreq), q(Fq), gain(1.0), abovenq(false), - oldabovenq(false) + oldabovenq(false), + samplerate_f(srate), + halfsamplerate_f(srate/2.0f), + buffersize(bufsize), + buffersize_f(bufsize) { for(int i = 0; i < 3; ++i) coeff.c[i] = coeff.d[i] = oldCoeff.c[i] = oldCoeff.d[i] = 0.0f; @@ -74,8 +79,8 @@ void AnalogFilter::computefiltercoefs(void) //do not allow frequencies bigger than samplerate/2 float freq = this->freq; - if(freq > (synth->halfsamplerate_f - 500.0f)) { - freq = synth->halfsamplerate_f - 500.0f; + if(freq > (halfsamplerate_f - 500.0f)) { + freq = halfsamplerate_f - 500.0f; zerocoefs = true; } if(freq < 0.1f) @@ -98,7 +103,7 @@ void AnalogFilter::computefiltercoefs(void) float *d = coeff.d; //General Constants - const float omega = 2 * PI * freq / synth->samplerate_f; + const float omega = 2 * PI * freq / samplerate_f; const float sn = sinf(omega), cs = cosf(omega); float alpha, beta; @@ -109,7 +114,7 @@ void AnalogFilter::computefiltercoefs(void) switch(type) { case 0: //LPF 1 pole if(!zerocoefs) - tmp = expf(-2.0f * PI * freq / synth->samplerate_f); + tmp = expf(-2.0f * PI * freq / samplerate_f); else tmp = 0.0f; c[0] = 1.0f - tmp; @@ -121,7 +126,7 @@ void AnalogFilter::computefiltercoefs(void) break; case 1: //HPF 1 pole if(!zerocoefs) - tmp = expf(-2.0f * PI * freq / synth->samplerate_f); + tmp = expf(-2.0f * PI * freq / samplerate_f); else tmp = 0.0f; c[0] = (1.0f + tmp) / 2.0f; @@ -276,7 +281,7 @@ void AnalogFilter::setfreq(float frequency) rap = 1.0f / rap; oldabovenq = abovenq; - abovenq = frequency > (synth->halfsamplerate_f - 500.0f); + abovenq = frequency > (halfsamplerate_f - 500.0f); bool nyquistthresh = (abovenq ^ oldabovenq); @@ -331,7 +336,7 @@ void AnalogFilter::singlefilterout(float *smp, fstage &hist, const Coeff &coeff) { if(order == 1) //First order filter - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < buffersize; ++i) { float y0 = smp[i] * coeff.c[0] + hist.x1 * coeff.c[1] + hist.y1 * coeff.d[1]; hist.y1 = y0; @@ -339,7 +344,7 @@ void AnalogFilter::singlefilterout(float *smp, fstage &hist, smp[i] = y0; } if(order == 2) //Second order filter - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < buffersize; ++i) { float y0 = smp[i] * coeff.c[0] + hist.x1 * coeff.c[1] + hist.x2 * coeff.c[2] + hist.y1 * coeff.d[1] + hist.y2 * coeff.d[2]; @@ -359,26 +364,26 @@ void AnalogFilter::filterout(float *smp) if(needsinterpolation) { //Merge Filter at old coeff with new coeff float *ismp = getTmpBuffer(); - memcpy(ismp, smp, synth->bufferbytes); + memcpy(ismp, smp, buffersize*sizeof(float)); for(int i = 0; i < stages + 1; ++i) singlefilterout(ismp, oldHistory[i], oldCoeff); - for(int i = 0; i < synth->buffersize; ++i) { - float x = (float)i / synth->buffersize_f; + for(int i = 0; i < buffersize; ++i) { + float x = (float)i / buffersize_f; smp[i] = ismp[i] * (1.0f - x) + smp[i] * x; } returnTmpBuffer(ismp); needsinterpolation = false; } - for(int i = 0; i < synth->buffersize; ++i) + for(int i = 0; i < buffersize; ++i) smp[i] *= outgain; } float AnalogFilter::H(float freq) { - float fr = freq / synth->samplerate_f * PI * 2.0f; + float fr = freq / samplerate_f * PI * 2.0f; float x = coeff.c[0], y = 0.0f; for(int n = 1; n < 3; ++n) { x += cosf(n * fr) * coeff.c[n]; diff --git a/source/modules/carla_native/zynaddsubfx/DSP/AnalogFilter.h b/source/modules/carla_native/zynaddsubfx/DSP/AnalogFilter.h index 5556c502d..b1ab8280a 100644 --- a/source/modules/carla_native/zynaddsubfx/DSP/AnalogFilter.h +++ b/source/modules/carla_native/zynaddsubfx/DSP/AnalogFilter.h @@ -35,7 +35,7 @@ class AnalogFilter:public Filter { public: AnalogFilter(unsigned char Ftype, float Ffreq, float Fq, - unsigned char Fstages); + unsigned char Fstages, float srate, int bufsize); ~AnalogFilter(); void filterout(float *smp); void setfreq(float frequency); @@ -79,6 +79,11 @@ class AnalogFilter:public Filter bool abovenq, //if the frequency is above the nyquist oldabovenq; //if the last time was above nyquist //(used to see if it needs interpolation) + + float samplerate_f; + float halfsamplerate_f; + int buffersize; + float buffersize_f; }; diff --git a/source/modules/carla_native/zynaddsubfx/DSP/Filter.cpp b/source/modules/carla_native/zynaddsubfx/DSP/Filter.cpp index 7c7e92c86..911a706cf 100644 --- a/source/modules/carla_native/zynaddsubfx/DSP/Filter.cpp +++ b/source/modules/carla_native/zynaddsubfx/DSP/Filter.cpp @@ -29,24 +29,29 @@ #include "SVFilter.h" #include "../Params/FilterParams.h" -Filter *Filter::generate(FilterParams *pars) +Filter *Filter::generate(FilterParams *pars, float srate, int bufsize) { + if (srate == 0.0f) + srate = synth->samplerate_f; + if (bufsize == 0) + bufsize = synth->buffersize; + unsigned char Ftype = pars->Ptype; unsigned char Fstages = pars->Pstages; Filter *filter; switch(pars->Pcategory) { case 1: - filter = new FormantFilter(pars); + filter = new FormantFilter(pars, srate, bufsize); break; case 2: - filter = new SVFilter(Ftype, 1000.0f, pars->getq(), Fstages); + filter = new SVFilter(Ftype, 1000.0f, pars->getq(), Fstages, srate, bufsize); filter->outgain = dB2rap(pars->getgain()); if(filter->outgain > 1.0f) filter->outgain = sqrt(filter->outgain); break; default: - filter = new AnalogFilter(Ftype, 1000.0f, pars->getq(), Fstages); + filter = new AnalogFilter(Ftype, 1000.0f, pars->getq(), Fstages, srate, bufsize); if((Ftype >= 6) && (Ftype <= 8)) filter->setgain(pars->getgain()); else diff --git a/source/modules/carla_native/zynaddsubfx/DSP/Filter.h b/source/modules/carla_native/zynaddsubfx/DSP/Filter.h index 41761e50d..a526bba9d 100644 --- a/source/modules/carla_native/zynaddsubfx/DSP/Filter.h +++ b/source/modules/carla_native/zynaddsubfx/DSP/Filter.h @@ -29,7 +29,7 @@ class Filter { public: static float getrealfreq(float freqpitch); - static Filter *generate(class FilterParams * pars); + static Filter *generate(class FilterParams * pars, float srate = 0, int bufsize = 0); virtual ~Filter() {} virtual void filterout(float *smp) = 0; diff --git a/source/modules/carla_native/zynaddsubfx/DSP/FormantFilter.cpp b/source/modules/carla_native/zynaddsubfx/DSP/FormantFilter.cpp index 5df27dfb6..3db8a9c75 100644 --- a/source/modules/carla_native/zynaddsubfx/DSP/FormantFilter.cpp +++ b/source/modules/carla_native/zynaddsubfx/DSP/FormantFilter.cpp @@ -27,11 +27,12 @@ #include "AnalogFilter.h" #include "../Params/FilterParams.h" -FormantFilter::FormantFilter(FilterParams *pars) +FormantFilter::FormantFilter(FilterParams *pars, float srate, int bufsize) { + buffersize = bufsize; numformants = pars->Pnumformants; for(int i = 0; i < numformants; ++i) - formant[i] = new AnalogFilter(4 /*BPF*/, 1000.0f, 10.0f, pars->Pstages); + formant[i] = new AnalogFilter(4 /*BPF*/, 1000.0f, 10.0f, pars->Pstages, srate, bufsize); cleanup(); for(int j = 0; j < FF_MAX_VOWELS; ++j) @@ -205,24 +206,24 @@ void FormantFilter::filterout(float *smp) { float *inbuffer = getTmpBuffer(); - memcpy(inbuffer, smp, synth->bufferbytes); - memset(smp, 0, synth->bufferbytes); + memcpy(inbuffer, smp, buffersize*sizeof(float)); + memset(smp, 0, buffersize*sizeof(float)); for(int j = 0; j < numformants; ++j) { float *tmpbuf = getTmpBuffer(); - for(int i = 0; i < synth->buffersize; ++i) + for(int i = 0; i < buffersize; ++i) tmpbuf[i] = inbuffer[i] * outgain; formant[j]->filterout(tmpbuf); if(ABOVE_AMPLITUDE_THRESHOLD(oldformantamp[j], currentformants[j].amp)) - for(int i = 0; i < synth->buffersize; ++i) + for(int i = 0; i < buffersize; ++i) smp[i] += tmpbuf[i] * INTERPOLATE_AMPLITUDE(oldformantamp[j], currentformants[j].amp, i, - synth->buffersize); + buffersize); else - for(int i = 0; i < synth->buffersize; ++i) + for(int i = 0; i < buffersize; ++i) smp[i] += tmpbuf[i] * currentformants[j].amp; returnTmpBuffer(tmpbuf); oldformantamp[j] = currentformants[j].amp; diff --git a/source/modules/carla_native/zynaddsubfx/DSP/FormantFilter.h b/source/modules/carla_native/zynaddsubfx/DSP/FormantFilter.h index 03b52cc6e..ce168ff1b 100644 --- a/source/modules/carla_native/zynaddsubfx/DSP/FormantFilter.h +++ b/source/modules/carla_native/zynaddsubfx/DSP/FormantFilter.h @@ -30,7 +30,7 @@ class FormantFilter:public Filter { public: - FormantFilter(class FilterParams *pars); + FormantFilter(class FilterParams *pars, float srate, int bufsize); ~FormantFilter(); void filterout(float *smp); void setfreq(float frequency); @@ -61,6 +61,8 @@ class FormantFilter:public Filter float oldinput, slowinput; float Qfactor, formantslowness, oldQfactor; float vowelclearness, sequencestretch; + + int buffersize; }; #endif diff --git a/source/modules/carla_native/zynaddsubfx/DSP/SVFilter.cpp b/source/modules/carla_native/zynaddsubfx/DSP/SVFilter.cpp index 0431227d1..5641bddf2 100644 --- a/source/modules/carla_native/zynaddsubfx/DSP/SVFilter.cpp +++ b/source/modules/carla_native/zynaddsubfx/DSP/SVFilter.cpp @@ -29,14 +29,16 @@ #include "SVFilter.h" SVFilter::SVFilter(unsigned char Ftype, float Ffreq, float Fq, - unsigned char Fstages) + unsigned char Fstages, float srate, int bufsize) :type(Ftype), stages(Fstages), freq(Ffreq), q(Fq), gain(1.0f), needsinterpolation(false), - firsttime(true) + firsttime(true), + samplerate_f(srate), + buffersize(bufsize) { if(stages >= MAX_FILTER_STAGES) stages = MAX_FILTER_STAGES; @@ -58,7 +60,7 @@ void SVFilter::cleanup() void SVFilter::computefiltercoefs(void) { - par.f = freq / synth->samplerate_f * 4.0f; + par.f = freq / samplerate_f * 4.0f; if(par.f > 0.99999f) par.f = 0.99999f; par.q = 1.0f - atanf(sqrtf(q)) * 2.0f / PI; @@ -76,7 +78,7 @@ void SVFilter::setfreq(float frequency) rap = 1.0f / rap; oldabovenq = abovenq; - abovenq = frequency > (synth->samplerate_f / 2 - 500.0f); + abovenq = frequency > (samplerate_f / 2 - 500.0f); bool nyquistthresh = (abovenq ^ oldabovenq); @@ -144,7 +146,7 @@ void SVFilter::singlefilterout(float *smp, fstage &x, parameters &par) errx(1, "Impossible SVFilter type encountered [%d]", type); } - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < buffersize; ++i) { x.low = x.low + par.f * x.band; x.high = par.q_sqrt * smp[i] - x.low - par.q * x.band; x.band = par.f * x.high + x.band; @@ -160,19 +162,19 @@ void SVFilter::filterout(float *smp) if(needsinterpolation) { float *ismp = getTmpBuffer(); - memcpy(ismp, smp, synth->bufferbytes); + memcpy(ismp, smp, buffersize*sizeof(float)); for(int i = 0; i < stages + 1; ++i) singlefilterout(ismp, st[i], ipar); - for(int i = 0; i < synth->buffersize; ++i) { - float x = i / synth->buffersize_f; + for(int i = 0; i < buffersize; ++i) { + float x = i / (float)buffersize; smp[i] = ismp[i] * (1.0f - x) + smp[i] * x; } returnTmpBuffer(ismp); needsinterpolation = false; } - for(int i = 0; i < synth->buffersize; ++i) + for(int i = 0; i < buffersize; ++i) smp[i] *= outgain; } diff --git a/source/modules/carla_native/zynaddsubfx/DSP/SVFilter.h b/source/modules/carla_native/zynaddsubfx/DSP/SVFilter.h index 2a17f0cb1..1b6ab7947 100644 --- a/source/modules/carla_native/zynaddsubfx/DSP/SVFilter.h +++ b/source/modules/carla_native/zynaddsubfx/DSP/SVFilter.h @@ -32,7 +32,7 @@ class SVFilter:public Filter SVFilter(unsigned char Ftype, float Ffreq, float Fq, - unsigned char Fstages); + unsigned char Fstages, float srate, int bufsize); ~SVFilter(); void filterout(float *smp); void setfreq(float frequency); @@ -64,6 +64,9 @@ class SVFilter:public Filter bool abovenq, //if the frequency is above the nyquist oldabovenq; bool needsinterpolation, firsttime; + + float samplerate_f; + int buffersize; }; #endif diff --git a/source/modules/carla_native/zynaddsubfx/Effects/Alienwah.cpp b/source/modules/carla_native/zynaddsubfx/Effects/Alienwah.cpp index b3110bac8..f5bd3aa6e 100644 --- a/source/modules/carla_native/zynaddsubfx/Effects/Alienwah.cpp +++ b/source/modules/carla_native/zynaddsubfx/Effects/Alienwah.cpp @@ -23,8 +23,9 @@ #include #include "Alienwah.h" -Alienwah::Alienwah(bool insertion_, float *efxoutl_, float *efxoutr_) - :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0), +Alienwah::Alienwah(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize) + :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0, srate, bufsize), + lfo(srate, bufsize), oldl(NULL), oldr(NULL) { @@ -58,8 +59,8 @@ void Alienwah::out(const Stereo &smp) clfol = complex(cosf(lfol + phase) * fb, sinf(lfol + phase) * fb); //rework clfor = complex(cosf(lfor + phase) * fb, sinf(lfor + phase) * fb); //rework - for(int i = 0; i < synth->buffersize; ++i) { - float x = ((float) i) / synth->buffersize_f; + for(int i = 0; i < buffersize; ++i) { + float x = float(i) / float(buffersize); float x1 = 1.0f - x; //left complex tmp = clfol * x + oldclfol * x1; diff --git a/source/modules/carla_native/zynaddsubfx/Effects/Alienwah.h b/source/modules/carla_native/zynaddsubfx/Effects/Alienwah.h index 4e0ea0ac7..52019ac94 100644 --- a/source/modules/carla_native/zynaddsubfx/Effects/Alienwah.h +++ b/source/modules/carla_native/zynaddsubfx/Effects/Alienwah.h @@ -44,7 +44,8 @@ class Alienwah:public Effect */ Alienwah(bool insertion_, float *const efxoutl_, - float *const efxoutr_); + float *const efxoutr_, + unsigned int srate, int bufsize); ~Alienwah(); void out(const Stereo &smp); diff --git a/source/modules/carla_native/zynaddsubfx/Effects/Chorus.cpp b/source/modules/carla_native/zynaddsubfx/Effects/Chorus.cpp index ad29df6ed..7421a17c0 100644 --- a/source/modules/carla_native/zynaddsubfx/Effects/Chorus.cpp +++ b/source/modules/carla_native/zynaddsubfx/Effects/Chorus.cpp @@ -26,9 +26,10 @@ using namespace std; -Chorus::Chorus(bool insertion_, float *const efxoutl_, float *efxoutr_) - :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0), - maxdelay((int)(MAX_CHORUS_DELAY / 1000.0f * synth->samplerate_f)), +Chorus::Chorus(bool insertion_, float *const efxoutl_, float *efxoutr_, unsigned int srate, int bufsize) + :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0, srate, bufsize), + lfo(srate, bufsize), + maxdelay((int)(MAX_CHORUS_DELAY / 1000.0f * (float)srate)), delaySample(new float[maxdelay], new float[maxdelay]) { dlk = 0; @@ -51,7 +52,7 @@ Chorus::~Chorus() float Chorus::getdelay(float xlfo) { float result = - (Pflangemode) ? 0 : (delay + xlfo * depth) * synth->samplerate_f; + (Pflangemode) ? 0 : (delay + xlfo * depth) * (float)samplerate; //check if delay is too big (caused by bad setdelay() and setdepth() if((result + 0.5f) >= maxdelay) { @@ -75,7 +76,7 @@ void Chorus::out(const Stereo &input) dl2 = getdelay(lfol); dr2 = getdelay(lfor); - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < buffersize; ++i) { float inL = input.l[i]; float inR = input.r[i]; //LRcross @@ -87,7 +88,7 @@ void Chorus::out(const Stereo &input) //compute the delay in samples using linear interpolation between the lfo delays float mdel = - (dl1 * (synth->buffersize - i) + dl2 * i) / synth->buffersize_f; + (dl1 * (buffersize - i) + dl2 * i) / (float)buffersize; if(++dlk >= maxdelay) dlk = 0; float tmp = dlk - mdel + maxdelay * 2.0f; //where should I get the sample from @@ -105,7 +106,7 @@ void Chorus::out(const Stereo &input) //Right channel //compute the delay in samples using linear interpolation between the lfo delays - mdel = (dr1 * (synth->buffersize - i) + dr2 * i) / synth->buffersize_f; + mdel = (dr1 * (buffersize - i) + dr2 * i) / (float)buffersize; if(++drk >= maxdelay) drk = 0; tmp = drk * 1.0f - mdel + maxdelay * 2.0f; //where should I get the sample from @@ -122,12 +123,12 @@ void Chorus::out(const Stereo &input) } if(Poutsub) - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < buffersize; ++i) { efxoutl[i] *= -1.0f; efxoutr[i] *= -1.0f; } - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < buffersize; ++i) { efxoutl[i] *= pangainL; efxoutr[i] *= pangainR; } diff --git a/source/modules/carla_native/zynaddsubfx/Effects/Chorus.h b/source/modules/carla_native/zynaddsubfx/Effects/Chorus.h index ac9e95a0d..7772d4668 100644 --- a/source/modules/carla_native/zynaddsubfx/Effects/Chorus.h +++ b/source/modules/carla_native/zynaddsubfx/Effects/Chorus.h @@ -32,7 +32,7 @@ class Chorus:public Effect { public: - Chorus(bool insertion_, float *efxoutl_, float *efxoutr_); + Chorus(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize); /**Destructor*/ ~Chorus(); void out(const Stereo &input); diff --git a/source/modules/carla_native/zynaddsubfx/Effects/Distorsion.cpp b/source/modules/carla_native/zynaddsubfx/Effects/Distorsion.cpp index 85d264523..0c6d95c8c 100644 --- a/source/modules/carla_native/zynaddsubfx/Effects/Distorsion.cpp +++ b/source/modules/carla_native/zynaddsubfx/Effects/Distorsion.cpp @@ -25,8 +25,8 @@ #include "../Misc/WaveShapeSmps.h" #include -Distorsion::Distorsion(bool insertion_, float *efxoutl_, float *efxoutr_) - :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0), +Distorsion::Distorsion(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize) + :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0, srate, bufsize), Pvolume(50), Pdrive(90), Plevel(64), @@ -37,10 +37,10 @@ Distorsion::Distorsion(bool insertion_, float *efxoutl_, float *efxoutr_) Pstereo(0), Pprefiltering(0) { - lpfl = new AnalogFilter(2, 22000, 1, 0); - lpfr = new AnalogFilter(2, 22000, 1, 0); - hpfl = new AnalogFilter(3, 20, 1, 0); - hpfr = new AnalogFilter(3, 20, 1, 0); + lpfl = new AnalogFilter(2, 22000, 1, 0, srate, bufsize); + lpfr = new AnalogFilter(2, 22000, 1, 0, srate, bufsize); + hpfl = new AnalogFilter(3, 20, 1, 0, srate, bufsize); + hpfr = new AnalogFilter(3, 20, 1, 0, srate, bufsize); setpreset(Ppreset); cleanup(); } @@ -83,29 +83,29 @@ void Distorsion::out(const Stereo &smp) inputvol *= -1.0f; if(Pstereo) //Stereo - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < buffersize; ++i) { efxoutl[i] = smp.l[i] * inputvol * pangainL; efxoutr[i] = smp.r[i] * inputvol * pangainR; } else //Mono - for(int i = 0; i < synth->buffersize; ++i) + for(int i = 0; i < buffersize; ++i) efxoutl[i] = (smp.l[i] * pangainL + smp.r[i] * pangainR) * inputvol; if(Pprefiltering) applyfilters(efxoutl, efxoutr); - waveShapeSmps(synth->buffersize, efxoutl, Ptype + 1, Pdrive); + waveShapeSmps(buffersize, efxoutl, Ptype + 1, Pdrive); if(Pstereo) - waveShapeSmps(synth->buffersize, efxoutr, Ptype + 1, Pdrive); + waveShapeSmps(buffersize, efxoutr, Ptype + 1, Pdrive); if(!Pprefiltering) applyfilters(efxoutl, efxoutr); if(!Pstereo) - memcpy(efxoutr, efxoutl, synth->bufferbytes); + memcpy(efxoutr, efxoutl, buffersize*sizeof(float)); float level = dB2rap(60.0f * Plevel / 127.0f - 40.0f); - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < buffersize; ++i) { float lout = efxoutl[i]; float rout = efxoutr[i]; float l = lout * (1.0f - lrcross) + rout * lrcross; diff --git a/source/modules/carla_native/zynaddsubfx/Effects/Distorsion.h b/source/modules/carla_native/zynaddsubfx/Effects/Distorsion.h index eb06a9cc0..9d577ddd8 100644 --- a/source/modules/carla_native/zynaddsubfx/Effects/Distorsion.h +++ b/source/modules/carla_native/zynaddsubfx/Effects/Distorsion.h @@ -29,7 +29,7 @@ class Distorsion:public Effect { public: - Distorsion(bool insertion, float *efxoutl_, float *efxoutr_); + Distorsion(bool insertion, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize); ~Distorsion(); void out(const Stereo &smp); void setpreset(unsigned char npreset); diff --git a/source/modules/carla_native/zynaddsubfx/Effects/DynamicFilter.cpp b/source/modules/carla_native/zynaddsubfx/Effects/DynamicFilter.cpp index 74731da0e..650a882be 100644 --- a/source/modules/carla_native/zynaddsubfx/Effects/DynamicFilter.cpp +++ b/source/modules/carla_native/zynaddsubfx/Effects/DynamicFilter.cpp @@ -24,8 +24,9 @@ #include "DynamicFilter.h" #include "../DSP/Filter.h" -DynamicFilter::DynamicFilter(bool insertion_, float *efxoutl_, float *efxoutr_) - :Effect(insertion_, efxoutl_, efxoutr_, new FilterParams(0, 64, 64), 0), +DynamicFilter::DynamicFilter(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize) + :Effect(insertion_, efxoutl_, efxoutr_, new FilterParams(0, 64, 64), 0, srate, bufsize), + lfo(srate, bufsize), Pvolume(110), Pdepth(0), Pampsns(90), @@ -61,7 +62,7 @@ void DynamicFilter::out(const Stereo &smp) const float freq = filterpars->getfreq(); const float q = filterpars->getq(); - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < buffersize; ++i) { efxoutl[i] = smp.l[i]; efxoutr[i] = smp.r[i]; @@ -85,7 +86,7 @@ void DynamicFilter::out(const Stereo &smp) filterr->filterout(efxoutr); //panning - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < buffersize; ++i) { efxoutl[i] *= pangainL; efxoutr[i] *= pangainR; } @@ -130,8 +131,8 @@ void DynamicFilter::reinitfilter(void) { delete filterl; delete filterr; - filterl = Filter::generate(filterpars); - filterr = Filter::generate(filterpars); + filterl = Filter::generate(filterpars, samplerate, buffersize); + filterr = Filter::generate(filterpars, samplerate, buffersize); } void DynamicFilter::setpreset(unsigned char npreset) diff --git a/source/modules/carla_native/zynaddsubfx/Effects/DynamicFilter.h b/source/modules/carla_native/zynaddsubfx/Effects/DynamicFilter.h index 0b2c40d30..91d1f5e49 100644 --- a/source/modules/carla_native/zynaddsubfx/Effects/DynamicFilter.h +++ b/source/modules/carla_native/zynaddsubfx/Effects/DynamicFilter.h @@ -30,7 +30,7 @@ class DynamicFilter:public Effect { public: - DynamicFilter(bool insertion_, float *efxoutl_, float *efxoutr_); + DynamicFilter(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize); ~DynamicFilter(); void out(const Stereo &smp); diff --git a/source/modules/carla_native/zynaddsubfx/Effects/EQ.cpp b/source/modules/carla_native/zynaddsubfx/Effects/EQ.cpp index 8d354050f..e03fcef71 100644 --- a/source/modules/carla_native/zynaddsubfx/Effects/EQ.cpp +++ b/source/modules/carla_native/zynaddsubfx/Effects/EQ.cpp @@ -24,8 +24,8 @@ #include "EQ.h" #include "../DSP/AnalogFilter.h" -EQ::EQ(bool insertion_, float *efxoutl_, float *efxoutr_) - :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0) +EQ::EQ(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize) + :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0, srate, bufsize) { for(int i = 0; i < MAX_EQ_BANDS; ++i) { filter[i].Ptype = 0; @@ -33,8 +33,8 @@ EQ::EQ(bool insertion_, float *efxoutl_, float *efxoutr_) filter[i].Pgain = 64; filter[i].Pq = 64; filter[i].Pstages = 0; - filter[i].l = new AnalogFilter(6, 1000.0f, 1.0f, 0); - filter[i].r = new AnalogFilter(6, 1000.0f, 1.0f, 0); + filter[i].l = new AnalogFilter(6, 1000.0f, 1.0f, 0, srate, bufsize); + filter[i].r = new AnalogFilter(6, 1000.0f, 1.0f, 0, srate, bufsize); } //default values Pvolume = 50; @@ -56,7 +56,7 @@ void EQ::cleanup(void) //Effect output void EQ::out(const Stereo &smp) { - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < buffersize; ++i) { efxoutl[i] = smp.l[i] * volume; efxoutr[i] = smp.r[i] * volume; } diff --git a/source/modules/carla_native/zynaddsubfx/Effects/EQ.h b/source/modules/carla_native/zynaddsubfx/Effects/EQ.h index 9dd14fbfb..b2e9e89a9 100644 --- a/source/modules/carla_native/zynaddsubfx/Effects/EQ.h +++ b/source/modules/carla_native/zynaddsubfx/Effects/EQ.h @@ -29,7 +29,7 @@ class EQ:public Effect { public: - EQ(bool insertion_, float *efxoutl_, float *efxoutr_); + EQ(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize); ~EQ() {} void out(const Stereo &smp); void setpreset(unsigned char npreset); diff --git a/source/modules/carla_native/zynaddsubfx/Effects/Echo.cpp b/source/modules/carla_native/zynaddsubfx/Effects/Echo.cpp index 803bbf387..175b94240 100644 --- a/source/modules/carla_native/zynaddsubfx/Effects/Echo.cpp +++ b/source/modules/carla_native/zynaddsubfx/Effects/Echo.cpp @@ -27,8 +27,8 @@ #define MAX_DELAY 2 -Echo::Echo(bool insertion_, float *efxoutl_, float *efxoutr_) - :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0), +Echo::Echo(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize) + :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0, srate, bufsize), Pvolume(50), Pdelay(60), Plrdelay(100), @@ -37,8 +37,8 @@ Echo::Echo(bool insertion_, float *efxoutl_, float *efxoutr_) delayTime(1), lrdelay(0), avgDelay(0), - delay(new float[(int)(MAX_DELAY * synth->samplerate)], - new float[(int)(MAX_DELAY * synth->samplerate)]), + delay(new float[(int)(MAX_DELAY * srate)], + new float[(int)(MAX_DELAY * srate)]), old(0.0f), pos(0), delta(1), @@ -57,8 +57,8 @@ Echo::~Echo() //Cleanup the effect void Echo::cleanup(void) { - memset(delay.l, 0, MAX_DELAY * synth->samplerate * sizeof(float)); - memset(delay.r, 0, MAX_DELAY * synth->samplerate * sizeof(float)); + memset(delay.l, 0, MAX_DELAY * samplerate * sizeof(float)); + memset(delay.r, 0, MAX_DELAY * samplerate * sizeof(float)); old = Stereo(0.0f); } @@ -77,14 +77,14 @@ void Echo::initdelays(void) //number of seconds to delay right chan float dr = avgDelay + lrdelay; - ndelta.l = max(1, (int) (dl * synth->samplerate)); - ndelta.r = max(1, (int) (dr * synth->samplerate)); + ndelta.l = max(1, (int) (dl * samplerate)); + ndelta.r = max(1, (int) (dr * samplerate)); } //Effect output void Echo::out(const Stereo &input) { - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < buffersize; ++i) { float ldl = delay.l[pos.l]; float rdl = delay.r[pos.r]; ldl = ldl * (1.0f - lrcross) + rdl * lrcross; @@ -97,9 +97,9 @@ void Echo::out(const Stereo &input) rdl = input.r[i] * pangainR - rdl * fb; //LowPass Filter - old.l = delay.l[(pos.l + delta.l) % (MAX_DELAY * synth->samplerate)] = + old.l = delay.l[(pos.l + delta.l) % (MAX_DELAY * samplerate)] = ldl * hidamp + old.l * (1.0f - hidamp); - old.r = delay.r[(pos.r + delta.r) % (MAX_DELAY * synth->samplerate)] = + old.r = delay.r[(pos.r + delta.r) % (MAX_DELAY * samplerate)] = rdl * hidamp + old.r * (1.0f - hidamp); //increment @@ -107,8 +107,8 @@ void Echo::out(const Stereo &input) ++pos.r; // += delta.r; //ensure that pos is still in bounds - pos.l %= MAX_DELAY * synth->samplerate; - pos.r %= MAX_DELAY * synth->samplerate; + pos.l %= MAX_DELAY * samplerate; + pos.r %= MAX_DELAY * samplerate; //adjust delay if needed delta.l = (15 * delta.l + ndelta.l) / 16; diff --git a/source/modules/carla_native/zynaddsubfx/Effects/Echo.h b/source/modules/carla_native/zynaddsubfx/Effects/Echo.h index 6b79adcf1..ffc046778 100644 --- a/source/modules/carla_native/zynaddsubfx/Effects/Echo.h +++ b/source/modules/carla_native/zynaddsubfx/Effects/Echo.h @@ -30,7 +30,7 @@ class Echo:public Effect { public: - Echo(bool insertion_, float *efxoutl_, float *efxoutr_); + Echo(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize); ~Echo(); void out(const Stereo &input); diff --git a/source/modules/carla_native/zynaddsubfx/Effects/Effect.cpp b/source/modules/carla_native/zynaddsubfx/Effects/Effect.cpp index 42eee79a1..c43ee2bf7 100644 --- a/source/modules/carla_native/zynaddsubfx/Effects/Effect.cpp +++ b/source/modules/carla_native/zynaddsubfx/Effects/Effect.cpp @@ -26,12 +26,15 @@ #include Effect::Effect(bool insertion_, float *efxoutl_, float *efxoutr_, - FilterParams *filterpars_, unsigned char Ppreset_) + FilterParams *filterpars_, unsigned char Ppreset_, + unsigned int srate, int bufsize) :Ppreset(Ppreset_), efxoutl(efxoutl_), efxoutr(efxoutr_), filterpars(filterpars_), - insertion(insertion_) + insertion(insertion_), + samplerate(srate), + buffersize(bufsize) {} void Effect::out(float *const smpsl, float *const smpsr) diff --git a/source/modules/carla_native/zynaddsubfx/Effects/Effect.h b/source/modules/carla_native/zynaddsubfx/Effects/Effect.h index d4d4a46c8..022e35d3e 100644 --- a/source/modules/carla_native/zynaddsubfx/Effects/Effect.h +++ b/source/modules/carla_native/zynaddsubfx/Effects/Effect.h @@ -24,7 +24,6 @@ #define EFFECT_H #include "../Misc/Util.h" -#include "../globals.h" #include "../Params/FilterParams.h" #include "../Misc/Stereo.h" @@ -43,7 +42,8 @@ class Effect * @param Ppreset_ chosen preset * @return Initialized Effect object*/ Effect(bool insertion_, float *efxoutl_, float *efxoutr_, - FilterParams *filterpars_, unsigned char Ppreset_); + FilterParams *filterpars_, unsigned char Ppreset_, + unsigned int srate, int bufsize); virtual ~Effect() {} /** * Choose a preset @@ -100,6 +100,10 @@ class Effect float pangainR; char Plrcross; // L/R mix float lrcross; + + // current setup + unsigned int samplerate; + int buffersize; }; #endif diff --git a/source/modules/carla_native/zynaddsubfx/Effects/EffectLFO.cpp b/source/modules/carla_native/zynaddsubfx/Effects/EffectLFO.cpp index f66b5fe07..1694738ad 100644 --- a/source/modules/carla_native/zynaddsubfx/Effects/EffectLFO.cpp +++ b/source/modules/carla_native/zynaddsubfx/Effects/EffectLFO.cpp @@ -25,7 +25,7 @@ #include -EffectLFO::EffectLFO(void) +EffectLFO::EffectLFO(float srate, float bufsize) :Pfreq(40), Prandomness(0), PLFOtype(0), @@ -36,7 +36,9 @@ EffectLFO::EffectLFO(void) ampl2(RND), ampr1(RND), ampr2(RND), - lfornd(0.0f) + lfornd(0.0f), + samplerate_f(srate), + buffersize_f(bufsize) { updateparams(); } @@ -47,7 +49,7 @@ EffectLFO::~EffectLFO() {} void EffectLFO::updateparams(void) { float lfofreq = (powf(2.0f, Pfreq / 127.0f * 10.0f) - 1.0f) * 0.03f; - incx = fabsf(lfofreq) * synth->buffersize_f / synth->samplerate_f; + incx = fabsf(lfofreq) * buffersize_f / samplerate_f; if(incx > 0.49999999f) incx = 0.499999999f; //Limit the Frequency diff --git a/source/modules/carla_native/zynaddsubfx/Effects/EffectLFO.h b/source/modules/carla_native/zynaddsubfx/Effects/EffectLFO.h index e9571b8c0..cb103638f 100644 --- a/source/modules/carla_native/zynaddsubfx/Effects/EffectLFO.h +++ b/source/modules/carla_native/zynaddsubfx/Effects/EffectLFO.h @@ -28,7 +28,7 @@ class EffectLFO { public: - EffectLFO(); + EffectLFO(float srate, float bufsize); ~EffectLFO(); void effectlfoout(float *outl, float *outr); void updateparams(void); @@ -45,6 +45,9 @@ class EffectLFO float lfointensity; float lfornd; char lfotype; + + float samplerate_f; + float buffersize_f; }; #endif diff --git a/source/modules/carla_native/zynaddsubfx/Effects/EffectMgr.cpp b/source/modules/carla_native/zynaddsubfx/Effects/EffectMgr.cpp index c2fce519e..08d4f1d88 100644 --- a/source/modules/carla_native/zynaddsubfx/Effects/EffectMgr.cpp +++ b/source/modules/carla_native/zynaddsubfx/Effects/EffectMgr.cpp @@ -76,28 +76,28 @@ void EffectMgr::changeeffect(int _nefx) delete efx; switch(nefx) { case 1: - efx = new Reverb(insertion, efxoutl, efxoutr); + efx = new Reverb(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize); break; case 2: - efx = new Echo(insertion, efxoutl, efxoutr); + efx = new Echo(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize); break; case 3: - efx = new Chorus(insertion, efxoutl, efxoutr); + efx = new Chorus(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize); break; case 4: - efx = new Phaser(insertion, efxoutl, efxoutr); + efx = new Phaser(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize); break; case 5: - efx = new Alienwah(insertion, efxoutl, efxoutr); + efx = new Alienwah(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize); break; case 6: - efx = new Distorsion(insertion, efxoutl, efxoutr); + efx = new Distorsion(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize); break; case 7: - efx = new EQ(insertion, efxoutl, efxoutr); + efx = new EQ(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize); break; case 8: - efx = new DynamicFilter(insertion, efxoutl, efxoutr); + efx = new DynamicFilter(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize); break; //put more effect here default: diff --git a/source/modules/carla_native/zynaddsubfx/Effects/Phaser.cpp b/source/modules/carla_native/zynaddsubfx/Effects/Phaser.cpp index 1dd26be1e..d2bec4ec7 100644 --- a/source/modules/carla_native/zynaddsubfx/Effects/Phaser.cpp +++ b/source/modules/carla_native/zynaddsubfx/Effects/Phaser.cpp @@ -39,8 +39,8 @@ using namespace std; #define ONE_ 0.99999f // To prevent LFO ever reaching 1.0f for filter stability purposes #define ZERO_ 0.00001f // Same idea as above. -Phaser::Phaser(const int &insertion_, float *efxoutl_, float *efxoutr_) - :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0), old(NULL), xn1(NULL), +Phaser::Phaser(const int &insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize) + :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0, srate, bufsize), lfo(srate, bufsize), old(NULL), xn1(NULL), yn1(NULL), diff(0.0f), oldgain(0.0f), fb(0.0f) { analog_setup(); @@ -72,8 +72,8 @@ void Phaser::analog_setup() Rmx = Rmin / Rmax; Rconst = 1.0f + Rmx; // Handle parallel resistor relationship C = 0.00000005f; // 50 nF - CFs = 2.0f * synth->samplerate_f * C; - invperiod = 1.0f / synth->buffersize_f; + CFs = 2.0f * float(samplerate) * C; + invperiod = 1.0f / float(buffersize); } Phaser::~Phaser() @@ -129,7 +129,7 @@ void Phaser::AnalogPhase(const Stereo &input) g = oldgain; oldgain = mod; - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < buffersize; ++i) { g.l += diff.l; // Linear interpolation between LFO samples g.r += diff.r; @@ -151,8 +151,8 @@ void Phaser::AnalogPhase(const Stereo &input) } if(Poutsub) { - invSignal(efxoutl, synth->buffersize); - invSignal(efxoutr, synth->buffersize); + invSignal(efxoutl, buffersize); + invSignal(efxoutr, buffersize); } } @@ -202,8 +202,8 @@ void Phaser::normalPhase(const Stereo &input) gain.l = limit(gain.l, ZERO_, ONE_); gain.r = limit(gain.r, ZERO_, ONE_); - for(int i = 0; i < synth->buffersize; ++i) { - float x = (float) i / synth->buffersize_f; + for(int i = 0; i < buffersize; ++i) { + float x = float(i) / float(buffersize); float x1 = 1.0f - x; //TODO think about making panning an external feature Stereo xn(input.l[i] * pangainL + fb.l, @@ -227,8 +227,8 @@ void Phaser::normalPhase(const Stereo &input) oldgain = gain; if(Poutsub) { - invSignal(efxoutl, synth->buffersize); - invSignal(efxoutr, synth->buffersize); + invSignal(efxoutl, buffersize); + invSignal(efxoutr, buffersize); } } diff --git a/source/modules/carla_native/zynaddsubfx/Effects/Phaser.h b/source/modules/carla_native/zynaddsubfx/Effects/Phaser.h index dd8a400aa..47961870d 100644 --- a/source/modules/carla_native/zynaddsubfx/Effects/Phaser.h +++ b/source/modules/carla_native/zynaddsubfx/Effects/Phaser.h @@ -35,7 +35,7 @@ class Phaser:public Effect { public: - Phaser(const int &insertion_, float *efxoutl_, float *efxoutr_); + Phaser(const int &insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize); ~Phaser(); void out(const Stereo &input); void setpreset(unsigned char npreset); diff --git a/source/modules/carla_native/zynaddsubfx/Effects/Reverb.cpp b/source/modules/carla_native/zynaddsubfx/Effects/Reverb.cpp index 2d7884eab..cd71d4da1 100644 --- a/source/modules/carla_native/zynaddsubfx/Effects/Reverb.cpp +++ b/source/modules/carla_native/zynaddsubfx/Effects/Reverb.cpp @@ -28,8 +28,8 @@ //todo: EarlyReflections, Prdelay, Perbalance -Reverb::Reverb(bool insertion_, float *efxoutl_, float *efxoutr_) - :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0), +Reverb::Reverb(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize) + :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0, srate, bufsize), // defaults Pvolume(48), Ptime(64), @@ -116,7 +116,7 @@ void Reverb::processmono(int ch, float *output, float *inputbuf) const int comblength = comblen[j]; float &lpcombj = lpcomb[j]; - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < buffersize; ++i) { float fbout = comb[j][ck] * combfb[j]; fbout = fbout * (1.0f - lohifb) + lpcombj * lohifb; lpcombj = fbout; @@ -132,7 +132,7 @@ void Reverb::processmono(int ch, float *output, float *inputbuf) for(int j = REV_APS * ch; j < REV_APS * (1 + ch); ++j) { int &ak = apk[j]; const int aplength = aplen[j]; - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < buffersize; ++i) { float tmp = ap[j][ak]; ap[j][ak] = 0.7f * tmp + output[i]; output[i] = tmp - 0.7f * ap[j][ak]; @@ -149,11 +149,11 @@ void Reverb::out(const Stereo &smp) return; float *inputbuf = getTmpBuffer(); - for(int i = 0; i < synth->buffersize; ++i) + for(int i = 0; i < buffersize; ++i) inputbuf[i] = (smp.l[i] + smp.r[i]) / 2.0f; if(idelay) - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < buffersize; ++i) { //Initial delay r float tmp = inputbuf[i] + idelay[idelayk] * idelayfb; inputbuf[i] = idelay[idelayk]; @@ -164,7 +164,7 @@ void Reverb::out(const Stereo &smp) } if(bandwidth) - bandwidth->process(synth->buffersize, inputbuf); + bandwidth->process(buffersize, inputbuf); if(lpf) lpf->filterout(inputbuf); @@ -181,7 +181,7 @@ void Reverb::out(const Stereo &smp) lvol *= 2.0f; rvol *= 2.0f; } - for(int i = 0; i < synth->buffersize; ++i) { + for(int i = 0; i < buffersize; ++i) { efxoutl[i] *= lvol; efxoutr[i] *= rvol; } @@ -210,7 +210,7 @@ void Reverb::settime(unsigned char _Ptime) for(int i = 0; i < REV_COMBS * 2; ++i) combfb[i] = - -expf((float)comblen[i] / synth->samplerate_f * logf(0.001f) / t); + -expf((float)comblen[i] / (float)samplerate * logf(0.001f) / t); //the feedback is negative because it removes the DC } @@ -241,7 +241,7 @@ void Reverb::setidelay(unsigned char _Pidelay) delete [] idelay; idelay = NULL; - idelaylen = (int) (synth->samplerate_f * delay / 1000); + idelaylen = (int) ((float)samplerate * delay / 1000.0f); if(idelaylen > 1) { idelayk = 0; idelay = new float[idelaylen]; @@ -266,7 +266,7 @@ void Reverb::sethpf(unsigned char _Phpf) else { float fr = expf(powf(Phpf / 127.0f, 0.5f) * logf(10000.0f)) + 20.0f; if(hpf == NULL) - hpf = new AnalogFilter(3, fr, 1, 0); + hpf = new AnalogFilter(3, fr, 1, 0, samplerate, buffersize); else hpf->setfreq(fr); } @@ -283,7 +283,7 @@ void Reverb::setlpf(unsigned char _Plpf) else { float fr = expf(powf(Plpf / 127.0f, 0.5f) * logf(25000.0f)) + 40.0f; if(!lpf) - lpf = new AnalogFilter(2, fr, 1, 0); + lpf = new AnalogFilter(2, fr, 1, 0, samplerate, buffersize); else lpf->setfreq(fr); } @@ -315,7 +315,7 @@ void Reverb::settype(unsigned char _Ptype) Ptype = NUM_TYPES - 1; // adjust the combs according to the samplerate - float samplerate_adjust = synth->samplerate_f / 44100.0f; + float samplerate_adjust = (float)samplerate / 44100.0f; float tmp; for(int i = 0; i < REV_COMBS * 2; ++i) { if(Ptype == 0) @@ -360,7 +360,7 @@ void Reverb::settype(unsigned char _Ptype) //not been verified yet. //As this cannot be resized in a RT context, a good upper bound should //be found - bandwidth = new Unison(synth->buffersize / 4 + 1, 2.0f); + bandwidth = new Unison(buffersize / 4 + 1, 2.0f); bandwidth->setSize(50); bandwidth->setBaseFrequency(1.0f); } diff --git a/source/modules/carla_native/zynaddsubfx/Effects/Reverb.h b/source/modules/carla_native/zynaddsubfx/Effects/Reverb.h index f84d806d5..107122993 100644 --- a/source/modules/carla_native/zynaddsubfx/Effects/Reverb.h +++ b/source/modules/carla_native/zynaddsubfx/Effects/Reverb.h @@ -32,7 +32,7 @@ class Reverb:public Effect { public: - Reverb(bool insertion_, float *efxoutl_, float *efxoutr_); + Reverb(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize); ~Reverb(); void out(const Stereo &smp); void cleanup(void); diff --git a/source/plugin/Makefile b/source/plugin/Makefile index 8b4d12ff9..b479390ad 100644 --- a/source/plugin/Makefile +++ b/source/plugin/Makefile @@ -45,7 +45,7 @@ endif # -------------------------------------------------------------- # Native -DGL_LIBS = -lX11 +DGL_LIBS = -lX11 -lXext ifeq ($(HAVE_OPENGL),true) LINK_FLAGS += $(shell pkg-config --libs gl) $(DGL_LIBS) @@ -76,6 +76,10 @@ LINK_FLAGS += $(EXTRA_LIBS) LIBS = ../modules/carla_native.a LIBS += ../modules/juce_audio_basics.a LIBS += ../modules/juce_core.a +LIBS += ../modules/juce_data_structures.a +LIBS += ../modules/juce_events.a +LIBS += ../modules/juce_graphics.a +LIBS += ../modules/juce_gui_basics.a LIBS += ../modules/rtmempool.a # ifeq ($(CARLA_PLUGIN_SUPPORT),true) @@ -143,7 +147,7 @@ carla-native-lv2-export.exe: carla-native-lv2-export.cpp.o $(LIBS) # -------------------------------------------------------------- .FORCE: -.PHONY: .FORCE +.PHONY: .FORCE carla-native-lv2-export carla-native-lv2-export.exe ../modules/%.a: .FORCE $(MAKE) -C ../modules $* diff --git a/source/plugin/carla-native-base.cpp b/source/plugin/carla-native-base.cpp index 1b0fe3731..988790be7 100644 --- a/source/plugin/carla-native-base.cpp +++ b/source/plugin/carla-native-base.cpp @@ -35,7 +35,8 @@ void carla_register_native_plugin_midiTranspose(); void carla_register_native_plugin_nekofilter(); // Simple plugins (C++) -void carla_register_native_plugin_vex(); +void carla_register_native_plugin_vex_fx(); +void carla_register_native_plugin_vex_synth(); #ifdef WANT_AUDIOFILE // AudioFile @@ -63,7 +64,8 @@ void carla_register_native_plugin_Notes(); #ifdef WANT_ZYNADDSUBFX // ZynAddSubFX -void carla_register_native_plugin_zynaddsubfx(); +void carla_register_native_plugin_zynaddsubfx_fx(); +void carla_register_native_plugin_zynaddsubfx_synth(); #endif } @@ -83,7 +85,8 @@ struct PluginListManager { carla_register_native_plugin_nekofilter(); // Simple plugins (C++) - carla_register_native_plugin_vex(); + carla_register_native_plugin_vex_fx(); + carla_register_native_plugin_vex_synth(); #ifdef WANT_AUDIOFILE // AudioFile @@ -111,7 +114,8 @@ struct PluginListManager { #ifdef WANT_ZYNADDSUBFX // ZynAddSubFX - carla_register_native_plugin_zynaddsubfx(); + carla_register_native_plugin_zynaddsubfx_fx(); + carla_register_native_plugin_zynaddsubfx_synth(); #endif }