| @@ -32,7 +32,8 @@ void carla_register_native_plugin_midiThrough(); | |||||
| void carla_register_native_plugin_midiTranspose(); | void carla_register_native_plugin_midiTranspose(); | ||||
| void carla_register_native_plugin_nekofilter(); | void carla_register_native_plugin_nekofilter(); | ||||
| void carla_register_native_plugin_sunvoxfile(); | 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 | #ifndef BUILD_BRIDGE | ||||
| // Carla | // Carla | ||||
| @@ -65,7 +66,8 @@ void carla_register_native_plugin_Notes(); | |||||
| #ifdef WANT_ZYNADDSUBFX | #ifdef WANT_ZYNADDSUBFX | ||||
| // ZynAddSubFX | // ZynAddSubFX | ||||
| void carla_register_native_plugin_zynaddsubfx(); | |||||
| void carla_register_native_plugin_zynaddsubfx_fx(); | |||||
| void carla_register_native_plugin_zynaddsubfx_synth(); | |||||
| #endif | #endif | ||||
| } | } | ||||
| @@ -80,7 +82,8 @@ void carla_register_all_plugins() | |||||
| carla_register_native_plugin_midiTranspose(); | carla_register_native_plugin_midiTranspose(); | ||||
| carla_register_native_plugin_nekofilter(); | carla_register_native_plugin_nekofilter(); | ||||
| //carla_register_native_plugin_sunvoxfile(); // unfinished | //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 | #ifndef BUILD_BRIDGE | ||||
| // Carla | // Carla | ||||
| @@ -113,7 +116,8 @@ void carla_register_all_plugins() | |||||
| #ifdef WANT_ZYNADDSUBFX | #ifdef WANT_ZYNADDSUBFX | ||||
| // ZynAddSubFX | // ZynAddSubFX | ||||
| carla_register_native_plugin_zynaddsubfx(); | |||||
| carla_register_native_plugin_zynaddsubfx_fx(); | |||||
| carla_register_native_plugin_zynaddsubfx_synth(); | |||||
| #endif | #endif | ||||
| } | } | ||||
| @@ -55,7 +55,8 @@ OBJS = \ | |||||
| # Simple plugins (C++) | # Simple plugins (C++) | ||||
| OBJS += \ | OBJS += \ | ||||
| vex.cpp.o \ | |||||
| vex-fx.cpp.o \ | |||||
| vex-synth.cpp.o \ | |||||
| vex-src.cpp.o | vex-src.cpp.o | ||||
| # AudioFile | # AudioFile | ||||
| @@ -92,7 +93,8 @@ OBJS += \ | |||||
| ifeq ($(HAVE_ZYN_DEPS),true) | ifeq ($(HAVE_ZYN_DEPS),true) | ||||
| # ZynAddSubFX | # ZynAddSubFX | ||||
| OBJS += \ | OBJS += \ | ||||
| zynaddsubfx.cpp.o \ | |||||
| zynaddsubfx-fx.cpp.o \ | |||||
| zynaddsubfx-synth.cpp.o \ | |||||
| zynaddsubfx-src.cpp.o | zynaddsubfx-src.cpp.o | ||||
| ifeq ($(HAVE_ZYN_UI_DEPS),true) | 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) | nekofilter.c.o: nekofilter.c nekofilter/*.c nekofilter/*.h $(CDEPS) | ||||
| $(CC) $< $(BUILD_C_FLAGS) -c -o $@ | $(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 $@ | $(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 $@ | $(CXX) $< $(ZYN_CXX_FLAGS) -c -o $@ | ||||
| zynaddsubfx/UI/%.cpp: zynaddsubfx/UI/%.fl | zynaddsubfx/UI/%.cpp: zynaddsubfx/UI/%.fl | ||||
| @@ -17,7 +17,7 @@ | |||||
| #include "CarlaNative.hpp" | #include "CarlaNative.hpp" | ||||
| #include "juce_core.h" | |||||
| #include "juce_gui_basics.h" | |||||
| using namespace juce; | using namespace juce; | ||||
| @@ -25,13 +25,8 @@ using namespace juce; | |||||
| #include "vex/VexChorus.h" | #include "vex/VexChorus.h" | ||||
| #include "vex/VexDelay.h" | #include "vex/VexDelay.h" | ||||
| #include "vex/VexReverb.h" | #include "vex/VexReverb.h" | ||||
| #include "vex/VexSyntModule.h" | |||||
| #include "vex/PeggyViewComponent.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<ComboBox> comboBox1; | |||||
| ScopedPointer<ComboBox> comboBox2; | |||||
| ScopedPointer<ComboBox> comboBox3; | |||||
| ScopedPointer<PeggyViewComponent> p1; | |||||
| ScopedPointer<PeggyViewComponent> p2; | |||||
| ScopedPointer<PeggyViewComponent> p3; | |||||
| VexArpSettings _d; | |||||
| }; | |||||
| // ----------------------------------------------------------------------- | |||||
| class VexArpPlugin : public PluginClass, | class VexArpPlugin : public PluginClass, | ||||
| public PeggyViewComponent::Callback | 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<ParameterHints>(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<ParameterHints>(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<VexEditorComponent> fView; | |||||
| ScopedPointer<HelperWindow> fWindow; | |||||
| PluginClassEND(VexSynthPlugin) | |||||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(VexSynthPlugin) | |||||
| }; | |||||
| // ----------------------------------------------------------------------- | |||||
| static const PluginDescriptor vexArpDesc = { | static const PluginDescriptor vexArpDesc = { | ||||
| /* category */ PLUGIN_CATEGORY_UTILITY, | /* category */ PLUGIN_CATEGORY_UTILITY, | ||||
| /* hints */ static_cast<PluginHints>(PLUGIN_HAS_GUI|PLUGIN_NEEDS_SINGLE_THREAD|PLUGIN_USES_TIME), | /* hints */ static_cast<PluginHints>(PLUGIN_HAS_GUI|PLUGIN_NEEDS_SINGLE_THREAD|PLUGIN_USES_TIME), | ||||
| @@ -1540,33 +939,15 @@ static const PluginDescriptor vexReverbDesc = { | |||||
| PluginDescriptorFILL(VexReverbPlugin) | PluginDescriptorFILL(VexReverbPlugin) | ||||
| }; | }; | ||||
| static const PluginDescriptor vexSynthDesc = { | |||||
| /* category */ PLUGIN_CATEGORY_SYNTH, | |||||
| /* hints */ static_cast<PluginHints>(PLUGIN_HAS_GUI|PLUGIN_NEEDS_SINGLE_THREAD|PLUGIN_USES_TIME), | |||||
| /* supports */ static_cast<PluginSupports>(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 | CARLA_EXPORT | ||||
| void carla_register_native_plugin_vex() | |||||
| void carla_register_native_plugin_vex_fx() | |||||
| { | { | ||||
| carla_register_native_plugin(&vexArpDesc); | carla_register_native_plugin(&vexArpDesc); | ||||
| carla_register_native_plugin(&vexChorusDesc); | carla_register_native_plugin(&vexChorusDesc); | ||||
| carla_register_native_plugin(&vexDelayDesc); | carla_register_native_plugin(&vexDelayDesc); | ||||
| carla_register_native_plugin(&vexReverbDesc); | carla_register_native_plugin(&vexReverbDesc); | ||||
| carla_register_native_plugin(&vexSynthDesc); | |||||
| } | } | ||||
| // ----------------------------------------------------------------------- | // ----------------------------------------------------------------------- | ||||
| @@ -0,0 +1,720 @@ | |||||
| /* | |||||
| * Carla Native Plugins | |||||
| * Copyright (C) 2013 Filipe Coelho <falktx@falktx.com> | |||||
| * | |||||
| * 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<ComboBox> comboBox1; | |||||
| ScopedPointer<ComboBox> comboBox2; | |||||
| ScopedPointer<ComboBox> comboBox3; | |||||
| ScopedPointer<PeggyViewComponent> p1; | |||||
| ScopedPointer<PeggyViewComponent> p2; | |||||
| ScopedPointer<PeggyViewComponent> 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<ParameterHints>(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<ParameterHints>(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<VexEditorComponent> fView; | |||||
| ScopedPointer<HelperWindow2> fWindow; | |||||
| PluginClassEND(VexSynthPlugin) | |||||
| CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(VexSynthPlugin) | |||||
| }; | |||||
| // ----------------------------------------------------------------------- | |||||
| static const PluginDescriptor vexSynthDesc = { | |||||
| /* category */ PLUGIN_CATEGORY_SYNTH, | |||||
| /* hints */ static_cast<PluginHints>(PLUGIN_HAS_GUI|PLUGIN_NEEDS_SINGLE_THREAD|PLUGIN_USES_TIME), | |||||
| /* supports */ static_cast<PluginSupports>(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); | |||||
| } | |||||
| // ----------------------------------------------------------------------- | |||||
| @@ -63,3 +63,22 @@ | |||||
| #include "zynaddsubfx/Synth/Resonance.cpp" | #include "zynaddsubfx/Synth/Resonance.cpp" | ||||
| #include "zynaddsubfx/Synth/SUBnote.cpp" | #include "zynaddsubfx/Synth/SUBnote.cpp" | ||||
| #include "zynaddsubfx/Synth/SynthNote.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<std::string> getSources(void){return std::set<std::string>();} | |||||
| std::set<std::string> getSinks(void){return std::set<std::string>();} | |||||
| std::string getSource(void){return "";} | |||||
| std::string getSink(void){return "";} | |||||
| void waveNew(WavFile*){} | |||||
| void waveStart(void){} | |||||
| void waveStop(void){} | |||||
| void waveEnd(void){} | |||||
| } | |||||
| @@ -0,0 +1,794 @@ | |||||
| /* | |||||
| * Carla Native Plugins | |||||
| * Copyright (C) 2012-2013 Filipe Coelho <falktx@falktx.com> | |||||
| * | |||||
| * 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 <cstdint> | |||||
| #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 <FL/Fl_Shared_Image.H> | |||||
| # include <FL/Fl_Tiled_Image.H> | |||||
| # include <FL/Fl_Theme.H> | |||||
| # ifdef override_hack | |||||
| # define override | |||||
| # undef override_hack | |||||
| # endif | |||||
| #endif | |||||
| #include <ctime> | |||||
| #include <set> | |||||
| #include <string> | |||||
| #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<const ProgramInfo*> 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<uint32_t>(synth->buffersize) && | |||||
| host->get_sample_rate(host->handle) == static_cast<double>(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<PluginHints>(PLUGIN_HAS_GUI|PLUGIN_USES_STATE), | |||||
| #else | |||||
| /* hints */ static_cast<PluginHints>(PLUGIN_USES_STATE), | |||||
| #endif | |||||
| /* supports */ static_cast<PluginSupports>(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); | |||||
| } | |||||
| // ----------------------------------------------------------------------- | |||||
| @@ -31,14 +31,19 @@ | |||||
| AnalogFilter::AnalogFilter(unsigned char Ftype, | AnalogFilter::AnalogFilter(unsigned char Ftype, | ||||
| float Ffreq, | float Ffreq, | ||||
| float Fq, | float Fq, | ||||
| unsigned char Fstages) | |||||
| unsigned char Fstages, | |||||
| float srate, int bufsize) | |||||
| :type(Ftype), | :type(Ftype), | ||||
| stages(Fstages), | stages(Fstages), | ||||
| freq(Ffreq), | freq(Ffreq), | ||||
| q(Fq), | q(Fq), | ||||
| gain(1.0), | gain(1.0), | ||||
| abovenq(false), | 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) | for(int i = 0; i < 3; ++i) | ||||
| coeff.c[i] = coeff.d[i] = oldCoeff.c[i] = oldCoeff.d[i] = 0.0f; | 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 | //do not allow frequencies bigger than samplerate/2 | ||||
| float freq = this->freq; | 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; | zerocoefs = true; | ||||
| } | } | ||||
| if(freq < 0.1f) | if(freq < 0.1f) | ||||
| @@ -98,7 +103,7 @@ void AnalogFilter::computefiltercoefs(void) | |||||
| float *d = coeff.d; | float *d = coeff.d; | ||||
| //General Constants | //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); | const float sn = sinf(omega), cs = cosf(omega); | ||||
| float alpha, beta; | float alpha, beta; | ||||
| @@ -109,7 +114,7 @@ void AnalogFilter::computefiltercoefs(void) | |||||
| switch(type) { | switch(type) { | ||||
| case 0: //LPF 1 pole | case 0: //LPF 1 pole | ||||
| if(!zerocoefs) | if(!zerocoefs) | ||||
| tmp = expf(-2.0f * PI * freq / synth->samplerate_f); | |||||
| tmp = expf(-2.0f * PI * freq / samplerate_f); | |||||
| else | else | ||||
| tmp = 0.0f; | tmp = 0.0f; | ||||
| c[0] = 1.0f - tmp; | c[0] = 1.0f - tmp; | ||||
| @@ -121,7 +126,7 @@ void AnalogFilter::computefiltercoefs(void) | |||||
| break; | break; | ||||
| case 1: //HPF 1 pole | case 1: //HPF 1 pole | ||||
| if(!zerocoefs) | if(!zerocoefs) | ||||
| tmp = expf(-2.0f * PI * freq / synth->samplerate_f); | |||||
| tmp = expf(-2.0f * PI * freq / samplerate_f); | |||||
| else | else | ||||
| tmp = 0.0f; | tmp = 0.0f; | ||||
| c[0] = (1.0f + tmp) / 2.0f; | c[0] = (1.0f + tmp) / 2.0f; | ||||
| @@ -276,7 +281,7 @@ void AnalogFilter::setfreq(float frequency) | |||||
| rap = 1.0f / rap; | rap = 1.0f / rap; | ||||
| oldabovenq = abovenq; | oldabovenq = abovenq; | ||||
| abovenq = frequency > (synth->halfsamplerate_f - 500.0f); | |||||
| abovenq = frequency > (halfsamplerate_f - 500.0f); | |||||
| bool nyquistthresh = (abovenq ^ oldabovenq); | bool nyquistthresh = (abovenq ^ oldabovenq); | ||||
| @@ -331,7 +336,7 @@ void AnalogFilter::singlefilterout(float *smp, fstage &hist, | |||||
| const Coeff &coeff) | const Coeff &coeff) | ||||
| { | { | ||||
| if(order == 1) //First order filter | 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] | float y0 = smp[i] * coeff.c[0] + hist.x1 * coeff.c[1] | ||||
| + hist.y1 * coeff.d[1]; | + hist.y1 * coeff.d[1]; | ||||
| hist.y1 = y0; | hist.y1 = y0; | ||||
| @@ -339,7 +344,7 @@ void AnalogFilter::singlefilterout(float *smp, fstage &hist, | |||||
| smp[i] = y0; | smp[i] = y0; | ||||
| } | } | ||||
| if(order == 2) //Second order filter | 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] | float y0 = smp[i] * coeff.c[0] + hist.x1 * coeff.c[1] | ||||
| + hist.x2 * coeff.c[2] + hist.y1 * coeff.d[1] | + hist.x2 * coeff.c[2] + hist.y1 * coeff.d[1] | ||||
| + hist.y2 * coeff.d[2]; | + hist.y2 * coeff.d[2]; | ||||
| @@ -359,26 +364,26 @@ void AnalogFilter::filterout(float *smp) | |||||
| if(needsinterpolation) { | if(needsinterpolation) { | ||||
| //Merge Filter at old coeff with new coeff | //Merge Filter at old coeff with new coeff | ||||
| float *ismp = getTmpBuffer(); | float *ismp = getTmpBuffer(); | ||||
| memcpy(ismp, smp, synth->bufferbytes); | |||||
| memcpy(ismp, smp, buffersize*sizeof(float)); | |||||
| for(int i = 0; i < stages + 1; ++i) | for(int i = 0; i < stages + 1; ++i) | ||||
| singlefilterout(ismp, oldHistory[i], oldCoeff); | 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; | smp[i] = ismp[i] * (1.0f - x) + smp[i] * x; | ||||
| } | } | ||||
| returnTmpBuffer(ismp); | returnTmpBuffer(ismp); | ||||
| needsinterpolation = false; | needsinterpolation = false; | ||||
| } | } | ||||
| for(int i = 0; i < synth->buffersize; ++i) | |||||
| for(int i = 0; i < buffersize; ++i) | |||||
| smp[i] *= outgain; | smp[i] *= outgain; | ||||
| } | } | ||||
| float AnalogFilter::H(float freq) | 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; | float x = coeff.c[0], y = 0.0f; | ||||
| for(int n = 1; n < 3; ++n) { | for(int n = 1; n < 3; ++n) { | ||||
| x += cosf(n * fr) * coeff.c[n]; | x += cosf(n * fr) * coeff.c[n]; | ||||
| @@ -35,7 +35,7 @@ class AnalogFilter:public Filter | |||||
| { | { | ||||
| public: | public: | ||||
| AnalogFilter(unsigned char Ftype, float Ffreq, float Fq, | AnalogFilter(unsigned char Ftype, float Ffreq, float Fq, | ||||
| unsigned char Fstages); | |||||
| unsigned char Fstages, float srate, int bufsize); | |||||
| ~AnalogFilter(); | ~AnalogFilter(); | ||||
| void filterout(float *smp); | void filterout(float *smp); | ||||
| void setfreq(float frequency); | void setfreq(float frequency); | ||||
| @@ -79,6 +79,11 @@ class AnalogFilter:public Filter | |||||
| bool abovenq, //if the frequency is above the nyquist | bool abovenq, //if the frequency is above the nyquist | ||||
| oldabovenq; //if the last time was above nyquist | oldabovenq; //if the last time was above nyquist | ||||
| //(used to see if it needs interpolation) | //(used to see if it needs interpolation) | ||||
| float samplerate_f; | |||||
| float halfsamplerate_f; | |||||
| int buffersize; | |||||
| float buffersize_f; | |||||
| }; | }; | ||||
| @@ -29,24 +29,29 @@ | |||||
| #include "SVFilter.h" | #include "SVFilter.h" | ||||
| #include "../Params/FilterParams.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 Ftype = pars->Ptype; | ||||
| unsigned char Fstages = pars->Pstages; | unsigned char Fstages = pars->Pstages; | ||||
| Filter *filter; | Filter *filter; | ||||
| switch(pars->Pcategory) { | switch(pars->Pcategory) { | ||||
| case 1: | case 1: | ||||
| filter = new FormantFilter(pars); | |||||
| filter = new FormantFilter(pars, srate, bufsize); | |||||
| break; | break; | ||||
| case 2: | 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()); | filter->outgain = dB2rap(pars->getgain()); | ||||
| if(filter->outgain > 1.0f) | if(filter->outgain > 1.0f) | ||||
| filter->outgain = sqrt(filter->outgain); | filter->outgain = sqrt(filter->outgain); | ||||
| break; | break; | ||||
| default: | 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)) | if((Ftype >= 6) && (Ftype <= 8)) | ||||
| filter->setgain(pars->getgain()); | filter->setgain(pars->getgain()); | ||||
| else | else | ||||
| @@ -29,7 +29,7 @@ class Filter | |||||
| { | { | ||||
| public: | public: | ||||
| static float getrealfreq(float freqpitch); | 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 ~Filter() {} | ||||
| virtual void filterout(float *smp) = 0; | virtual void filterout(float *smp) = 0; | ||||
| @@ -27,11 +27,12 @@ | |||||
| #include "AnalogFilter.h" | #include "AnalogFilter.h" | ||||
| #include "../Params/FilterParams.h" | #include "../Params/FilterParams.h" | ||||
| FormantFilter::FormantFilter(FilterParams *pars) | |||||
| FormantFilter::FormantFilter(FilterParams *pars, float srate, int bufsize) | |||||
| { | { | ||||
| buffersize = bufsize; | |||||
| numformants = pars->Pnumformants; | numformants = pars->Pnumformants; | ||||
| for(int i = 0; i < numformants; ++i) | 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(); | cleanup(); | ||||
| for(int j = 0; j < FF_MAX_VOWELS; ++j) | for(int j = 0; j < FF_MAX_VOWELS; ++j) | ||||
| @@ -205,24 +206,24 @@ void FormantFilter::filterout(float *smp) | |||||
| { | { | ||||
| float *inbuffer = getTmpBuffer(); | 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) { | for(int j = 0; j < numformants; ++j) { | ||||
| float *tmpbuf = getTmpBuffer(); | float *tmpbuf = getTmpBuffer(); | ||||
| for(int i = 0; i < synth->buffersize; ++i) | |||||
| for(int i = 0; i < buffersize; ++i) | |||||
| tmpbuf[i] = inbuffer[i] * outgain; | tmpbuf[i] = inbuffer[i] * outgain; | ||||
| formant[j]->filterout(tmpbuf); | formant[j]->filterout(tmpbuf); | ||||
| if(ABOVE_AMPLITUDE_THRESHOLD(oldformantamp[j], currentformants[j].amp)) | 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] | smp[i] += tmpbuf[i] | ||||
| * INTERPOLATE_AMPLITUDE(oldformantamp[j], | * INTERPOLATE_AMPLITUDE(oldformantamp[j], | ||||
| currentformants[j].amp, | currentformants[j].amp, | ||||
| i, | i, | ||||
| synth->buffersize); | |||||
| buffersize); | |||||
| else | else | ||||
| for(int i = 0; i < synth->buffersize; ++i) | |||||
| for(int i = 0; i < buffersize; ++i) | |||||
| smp[i] += tmpbuf[i] * currentformants[j].amp; | smp[i] += tmpbuf[i] * currentformants[j].amp; | ||||
| returnTmpBuffer(tmpbuf); | returnTmpBuffer(tmpbuf); | ||||
| oldformantamp[j] = currentformants[j].amp; | oldformantamp[j] = currentformants[j].amp; | ||||
| @@ -30,7 +30,7 @@ | |||||
| class FormantFilter:public Filter | class FormantFilter:public Filter | ||||
| { | { | ||||
| public: | public: | ||||
| FormantFilter(class FilterParams *pars); | |||||
| FormantFilter(class FilterParams *pars, float srate, int bufsize); | |||||
| ~FormantFilter(); | ~FormantFilter(); | ||||
| void filterout(float *smp); | void filterout(float *smp); | ||||
| void setfreq(float frequency); | void setfreq(float frequency); | ||||
| @@ -61,6 +61,8 @@ class FormantFilter:public Filter | |||||
| float oldinput, slowinput; | float oldinput, slowinput; | ||||
| float Qfactor, formantslowness, oldQfactor; | float Qfactor, formantslowness, oldQfactor; | ||||
| float vowelclearness, sequencestretch; | float vowelclearness, sequencestretch; | ||||
| int buffersize; | |||||
| }; | }; | ||||
| #endif | #endif | ||||
| @@ -29,14 +29,16 @@ | |||||
| #include "SVFilter.h" | #include "SVFilter.h" | ||||
| SVFilter::SVFilter(unsigned char Ftype, float Ffreq, float Fq, | SVFilter::SVFilter(unsigned char Ftype, float Ffreq, float Fq, | ||||
| unsigned char Fstages) | |||||
| unsigned char Fstages, float srate, int bufsize) | |||||
| :type(Ftype), | :type(Ftype), | ||||
| stages(Fstages), | stages(Fstages), | ||||
| freq(Ffreq), | freq(Ffreq), | ||||
| q(Fq), | q(Fq), | ||||
| gain(1.0f), | gain(1.0f), | ||||
| needsinterpolation(false), | needsinterpolation(false), | ||||
| firsttime(true) | |||||
| firsttime(true), | |||||
| samplerate_f(srate), | |||||
| buffersize(bufsize) | |||||
| { | { | ||||
| if(stages >= MAX_FILTER_STAGES) | if(stages >= MAX_FILTER_STAGES) | ||||
| stages = MAX_FILTER_STAGES; | stages = MAX_FILTER_STAGES; | ||||
| @@ -58,7 +60,7 @@ void SVFilter::cleanup() | |||||
| void SVFilter::computefiltercoefs(void) | void SVFilter::computefiltercoefs(void) | ||||
| { | { | ||||
| par.f = freq / synth->samplerate_f * 4.0f; | |||||
| par.f = freq / samplerate_f * 4.0f; | |||||
| if(par.f > 0.99999f) | if(par.f > 0.99999f) | ||||
| par.f = 0.99999f; | par.f = 0.99999f; | ||||
| par.q = 1.0f - atanf(sqrtf(q)) * 2.0f / PI; | par.q = 1.0f - atanf(sqrtf(q)) * 2.0f / PI; | ||||
| @@ -76,7 +78,7 @@ void SVFilter::setfreq(float frequency) | |||||
| rap = 1.0f / rap; | rap = 1.0f / rap; | ||||
| oldabovenq = abovenq; | oldabovenq = abovenq; | ||||
| abovenq = frequency > (synth->samplerate_f / 2 - 500.0f); | |||||
| abovenq = frequency > (samplerate_f / 2 - 500.0f); | |||||
| bool nyquistthresh = (abovenq ^ oldabovenq); | 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); | 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.low = x.low + par.f * x.band; | ||||
| x.high = par.q_sqrt * smp[i] - x.low - par.q * x.band; | x.high = par.q_sqrt * smp[i] - x.low - par.q * x.band; | ||||
| x.band = par.f * x.high + x.band; | x.band = par.f * x.high + x.band; | ||||
| @@ -160,19 +162,19 @@ void SVFilter::filterout(float *smp) | |||||
| if(needsinterpolation) { | if(needsinterpolation) { | ||||
| float *ismp = getTmpBuffer(); | float *ismp = getTmpBuffer(); | ||||
| memcpy(ismp, smp, synth->bufferbytes); | |||||
| memcpy(ismp, smp, buffersize*sizeof(float)); | |||||
| for(int i = 0; i < stages + 1; ++i) | for(int i = 0; i < stages + 1; ++i) | ||||
| singlefilterout(ismp, st[i], ipar); | 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; | smp[i] = ismp[i] * (1.0f - x) + smp[i] * x; | ||||
| } | } | ||||
| returnTmpBuffer(ismp); | returnTmpBuffer(ismp); | ||||
| needsinterpolation = false; | needsinterpolation = false; | ||||
| } | } | ||||
| for(int i = 0; i < synth->buffersize; ++i) | |||||
| for(int i = 0; i < buffersize; ++i) | |||||
| smp[i] *= outgain; | smp[i] *= outgain; | ||||
| } | } | ||||
| @@ -32,7 +32,7 @@ class SVFilter:public Filter | |||||
| SVFilter(unsigned char Ftype, | SVFilter(unsigned char Ftype, | ||||
| float Ffreq, | float Ffreq, | ||||
| float Fq, | float Fq, | ||||
| unsigned char Fstages); | |||||
| unsigned char Fstages, float srate, int bufsize); | |||||
| ~SVFilter(); | ~SVFilter(); | ||||
| void filterout(float *smp); | void filterout(float *smp); | ||||
| void setfreq(float frequency); | void setfreq(float frequency); | ||||
| @@ -64,6 +64,9 @@ class SVFilter:public Filter | |||||
| bool abovenq, //if the frequency is above the nyquist | bool abovenq, //if the frequency is above the nyquist | ||||
| oldabovenq; | oldabovenq; | ||||
| bool needsinterpolation, firsttime; | bool needsinterpolation, firsttime; | ||||
| float samplerate_f; | |||||
| int buffersize; | |||||
| }; | }; | ||||
| #endif | #endif | ||||
| @@ -23,8 +23,9 @@ | |||||
| #include <cmath> | #include <cmath> | ||||
| #include "Alienwah.h" | #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), | oldl(NULL), | ||||
| oldr(NULL) | oldr(NULL) | ||||
| { | { | ||||
| @@ -58,8 +59,8 @@ void Alienwah::out(const Stereo<float *> &smp) | |||||
| clfol = complex<float>(cosf(lfol + phase) * fb, sinf(lfol + phase) * fb); //rework | clfol = complex<float>(cosf(lfol + phase) * fb, sinf(lfol + phase) * fb); //rework | ||||
| clfor = complex<float>(cosf(lfor + phase) * fb, sinf(lfor + phase) * fb); //rework | clfor = complex<float>(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; | float x1 = 1.0f - x; | ||||
| //left | //left | ||||
| complex<float> tmp = clfol * x + oldclfol * x1; | complex<float> tmp = clfol * x + oldclfol * x1; | ||||
| @@ -44,7 +44,8 @@ class Alienwah:public Effect | |||||
| */ | */ | ||||
| Alienwah(bool insertion_, | Alienwah(bool insertion_, | ||||
| float *const efxoutl_, | float *const efxoutl_, | ||||
| float *const efxoutr_); | |||||
| float *const efxoutr_, | |||||
| unsigned int srate, int bufsize); | |||||
| ~Alienwah(); | ~Alienwah(); | ||||
| void out(const Stereo<float *> &smp); | void out(const Stereo<float *> &smp); | ||||
| @@ -26,9 +26,10 @@ | |||||
| using namespace std; | 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]) | delaySample(new float[maxdelay], new float[maxdelay]) | ||||
| { | { | ||||
| dlk = 0; | dlk = 0; | ||||
| @@ -51,7 +52,7 @@ Chorus::~Chorus() | |||||
| float Chorus::getdelay(float xlfo) | float Chorus::getdelay(float xlfo) | ||||
| { | { | ||||
| float result = | 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() | //check if delay is too big (caused by bad setdelay() and setdepth() | ||||
| if((result + 0.5f) >= maxdelay) { | if((result + 0.5f) >= maxdelay) { | ||||
| @@ -75,7 +76,7 @@ void Chorus::out(const Stereo<float *> &input) | |||||
| dl2 = getdelay(lfol); | dl2 = getdelay(lfol); | ||||
| dr2 = getdelay(lfor); | dr2 = getdelay(lfor); | ||||
| for(int i = 0; i < synth->buffersize; ++i) { | |||||
| for(int i = 0; i < buffersize; ++i) { | |||||
| float inL = input.l[i]; | float inL = input.l[i]; | ||||
| float inR = input.r[i]; | float inR = input.r[i]; | ||||
| //LRcross | //LRcross | ||||
| @@ -87,7 +88,7 @@ void Chorus::out(const Stereo<float *> &input) | |||||
| //compute the delay in samples using linear interpolation between the lfo delays | //compute the delay in samples using linear interpolation between the lfo delays | ||||
| float mdel = | float mdel = | ||||
| (dl1 * (synth->buffersize - i) + dl2 * i) / synth->buffersize_f; | |||||
| (dl1 * (buffersize - i) + dl2 * i) / (float)buffersize; | |||||
| if(++dlk >= maxdelay) | if(++dlk >= maxdelay) | ||||
| dlk = 0; | dlk = 0; | ||||
| float tmp = dlk - mdel + maxdelay * 2.0f; //where should I get the sample from | float tmp = dlk - mdel + maxdelay * 2.0f; //where should I get the sample from | ||||
| @@ -105,7 +106,7 @@ void Chorus::out(const Stereo<float *> &input) | |||||
| //Right channel | //Right channel | ||||
| //compute the delay in samples using linear interpolation between the lfo delays | //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) | if(++drk >= maxdelay) | ||||
| drk = 0; | drk = 0; | ||||
| tmp = drk * 1.0f - mdel + maxdelay * 2.0f; //where should I get the sample from | tmp = drk * 1.0f - mdel + maxdelay * 2.0f; //where should I get the sample from | ||||
| @@ -122,12 +123,12 @@ void Chorus::out(const Stereo<float *> &input) | |||||
| } | } | ||||
| if(Poutsub) | if(Poutsub) | ||||
| for(int i = 0; i < synth->buffersize; ++i) { | |||||
| for(int i = 0; i < buffersize; ++i) { | |||||
| efxoutl[i] *= -1.0f; | efxoutl[i] *= -1.0f; | ||||
| efxoutr[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; | efxoutl[i] *= pangainL; | ||||
| efxoutr[i] *= pangainR; | efxoutr[i] *= pangainR; | ||||
| } | } | ||||
| @@ -32,7 +32,7 @@ | |||||
| class Chorus:public Effect | class Chorus:public Effect | ||||
| { | { | ||||
| public: | public: | ||||
| Chorus(bool insertion_, float *efxoutl_, float *efxoutr_); | |||||
| Chorus(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize); | |||||
| /**Destructor*/ | /**Destructor*/ | ||||
| ~Chorus(); | ~Chorus(); | ||||
| void out(const Stereo<float *> &input); | void out(const Stereo<float *> &input); | ||||
| @@ -25,8 +25,8 @@ | |||||
| #include "../Misc/WaveShapeSmps.h" | #include "../Misc/WaveShapeSmps.h" | ||||
| #include <cmath> | #include <cmath> | ||||
| 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), | Pvolume(50), | ||||
| Pdrive(90), | Pdrive(90), | ||||
| Plevel(64), | Plevel(64), | ||||
| @@ -37,10 +37,10 @@ Distorsion::Distorsion(bool insertion_, float *efxoutl_, float *efxoutr_) | |||||
| Pstereo(0), | Pstereo(0), | ||||
| Pprefiltering(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); | setpreset(Ppreset); | ||||
| cleanup(); | cleanup(); | ||||
| } | } | ||||
| @@ -83,29 +83,29 @@ void Distorsion::out(const Stereo<float *> &smp) | |||||
| inputvol *= -1.0f; | inputvol *= -1.0f; | ||||
| if(Pstereo) //Stereo | 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; | efxoutl[i] = smp.l[i] * inputvol * pangainL; | ||||
| efxoutr[i] = smp.r[i] * inputvol * pangainR; | efxoutr[i] = smp.r[i] * inputvol * pangainR; | ||||
| } | } | ||||
| else //Mono | 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; | efxoutl[i] = (smp.l[i] * pangainL + smp.r[i] * pangainR) * inputvol; | ||||
| if(Pprefiltering) | if(Pprefiltering) | ||||
| applyfilters(efxoutl, efxoutr); | applyfilters(efxoutl, efxoutr); | ||||
| waveShapeSmps(synth->buffersize, efxoutl, Ptype + 1, Pdrive); | |||||
| waveShapeSmps(buffersize, efxoutl, Ptype + 1, Pdrive); | |||||
| if(Pstereo) | if(Pstereo) | ||||
| waveShapeSmps(synth->buffersize, efxoutr, Ptype + 1, Pdrive); | |||||
| waveShapeSmps(buffersize, efxoutr, Ptype + 1, Pdrive); | |||||
| if(!Pprefiltering) | if(!Pprefiltering) | ||||
| applyfilters(efxoutl, efxoutr); | applyfilters(efxoutl, efxoutr); | ||||
| if(!Pstereo) | if(!Pstereo) | ||||
| memcpy(efxoutr, efxoutl, synth->bufferbytes); | |||||
| memcpy(efxoutr, efxoutl, buffersize*sizeof(float)); | |||||
| float level = dB2rap(60.0f * Plevel / 127.0f - 40.0f); | 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 lout = efxoutl[i]; | ||||
| float rout = efxoutr[i]; | float rout = efxoutr[i]; | ||||
| float l = lout * (1.0f - lrcross) + rout * lrcross; | float l = lout * (1.0f - lrcross) + rout * lrcross; | ||||
| @@ -29,7 +29,7 @@ | |||||
| class Distorsion:public Effect | class Distorsion:public Effect | ||||
| { | { | ||||
| public: | public: | ||||
| Distorsion(bool insertion, float *efxoutl_, float *efxoutr_); | |||||
| Distorsion(bool insertion, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize); | |||||
| ~Distorsion(); | ~Distorsion(); | ||||
| void out(const Stereo<float *> &smp); | void out(const Stereo<float *> &smp); | ||||
| void setpreset(unsigned char npreset); | void setpreset(unsigned char npreset); | ||||
| @@ -24,8 +24,9 @@ | |||||
| #include "DynamicFilter.h" | #include "DynamicFilter.h" | ||||
| #include "../DSP/Filter.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), | Pvolume(110), | ||||
| Pdepth(0), | Pdepth(0), | ||||
| Pampsns(90), | Pampsns(90), | ||||
| @@ -61,7 +62,7 @@ void DynamicFilter::out(const Stereo<float *> &smp) | |||||
| const float freq = filterpars->getfreq(); | const float freq = filterpars->getfreq(); | ||||
| const float q = filterpars->getq(); | 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]; | efxoutl[i] = smp.l[i]; | ||||
| efxoutr[i] = smp.r[i]; | efxoutr[i] = smp.r[i]; | ||||
| @@ -85,7 +86,7 @@ void DynamicFilter::out(const Stereo<float *> &smp) | |||||
| filterr->filterout(efxoutr); | filterr->filterout(efxoutr); | ||||
| //panning | //panning | ||||
| for(int i = 0; i < synth->buffersize; ++i) { | |||||
| for(int i = 0; i < buffersize; ++i) { | |||||
| efxoutl[i] *= pangainL; | efxoutl[i] *= pangainL; | ||||
| efxoutr[i] *= pangainR; | efxoutr[i] *= pangainR; | ||||
| } | } | ||||
| @@ -130,8 +131,8 @@ void DynamicFilter::reinitfilter(void) | |||||
| { | { | ||||
| delete filterl; | delete filterl; | ||||
| delete filterr; | 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) | void DynamicFilter::setpreset(unsigned char npreset) | ||||
| @@ -30,7 +30,7 @@ | |||||
| class DynamicFilter:public Effect | class DynamicFilter:public Effect | ||||
| { | { | ||||
| public: | public: | ||||
| DynamicFilter(bool insertion_, float *efxoutl_, float *efxoutr_); | |||||
| DynamicFilter(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize); | |||||
| ~DynamicFilter(); | ~DynamicFilter(); | ||||
| void out(const Stereo<float *> &smp); | void out(const Stereo<float *> &smp); | ||||
| @@ -24,8 +24,8 @@ | |||||
| #include "EQ.h" | #include "EQ.h" | ||||
| #include "../DSP/AnalogFilter.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) { | for(int i = 0; i < MAX_EQ_BANDS; ++i) { | ||||
| filter[i].Ptype = 0; | filter[i].Ptype = 0; | ||||
| @@ -33,8 +33,8 @@ EQ::EQ(bool insertion_, float *efxoutl_, float *efxoutr_) | |||||
| filter[i].Pgain = 64; | filter[i].Pgain = 64; | ||||
| filter[i].Pq = 64; | filter[i].Pq = 64; | ||||
| filter[i].Pstages = 0; | 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 | //default values | ||||
| Pvolume = 50; | Pvolume = 50; | ||||
| @@ -56,7 +56,7 @@ void EQ::cleanup(void) | |||||
| //Effect output | //Effect output | ||||
| void EQ::out(const Stereo<float *> &smp) | void EQ::out(const Stereo<float *> &smp) | ||||
| { | { | ||||
| for(int i = 0; i < synth->buffersize; ++i) { | |||||
| for(int i = 0; i < buffersize; ++i) { | |||||
| efxoutl[i] = smp.l[i] * volume; | efxoutl[i] = smp.l[i] * volume; | ||||
| efxoutr[i] = smp.r[i] * volume; | efxoutr[i] = smp.r[i] * volume; | ||||
| } | } | ||||
| @@ -29,7 +29,7 @@ | |||||
| class EQ:public Effect | class EQ:public Effect | ||||
| { | { | ||||
| public: | public: | ||||
| EQ(bool insertion_, float *efxoutl_, float *efxoutr_); | |||||
| EQ(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize); | |||||
| ~EQ() {} | ~EQ() {} | ||||
| void out(const Stereo<float *> &smp); | void out(const Stereo<float *> &smp); | ||||
| void setpreset(unsigned char npreset); | void setpreset(unsigned char npreset); | ||||
| @@ -27,8 +27,8 @@ | |||||
| #define MAX_DELAY 2 | #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), | Pvolume(50), | ||||
| Pdelay(60), | Pdelay(60), | ||||
| Plrdelay(100), | Plrdelay(100), | ||||
| @@ -37,8 +37,8 @@ Echo::Echo(bool insertion_, float *efxoutl_, float *efxoutr_) | |||||
| delayTime(1), | delayTime(1), | ||||
| lrdelay(0), | lrdelay(0), | ||||
| avgDelay(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), | old(0.0f), | ||||
| pos(0), | pos(0), | ||||
| delta(1), | delta(1), | ||||
| @@ -57,8 +57,8 @@ Echo::~Echo() | |||||
| //Cleanup the effect | //Cleanup the effect | ||||
| void Echo::cleanup(void) | 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<float>(0.0f); | old = Stereo<float>(0.0f); | ||||
| } | } | ||||
| @@ -77,14 +77,14 @@ void Echo::initdelays(void) | |||||
| //number of seconds to delay right chan | //number of seconds to delay right chan | ||||
| float dr = avgDelay + lrdelay; | 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 | //Effect output | ||||
| void Echo::out(const Stereo<float *> &input) | void Echo::out(const Stereo<float *> &input) | ||||
| { | { | ||||
| for(int i = 0; i < synth->buffersize; ++i) { | |||||
| for(int i = 0; i < buffersize; ++i) { | |||||
| float ldl = delay.l[pos.l]; | float ldl = delay.l[pos.l]; | ||||
| float rdl = delay.r[pos.r]; | float rdl = delay.r[pos.r]; | ||||
| ldl = ldl * (1.0f - lrcross) + rdl * lrcross; | ldl = ldl * (1.0f - lrcross) + rdl * lrcross; | ||||
| @@ -97,9 +97,9 @@ void Echo::out(const Stereo<float *> &input) | |||||
| rdl = input.r[i] * pangainR - rdl * fb; | rdl = input.r[i] * pangainR - rdl * fb; | ||||
| //LowPass Filter | //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); | 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); | rdl * hidamp + old.r * (1.0f - hidamp); | ||||
| //increment | //increment | ||||
| @@ -107,8 +107,8 @@ void Echo::out(const Stereo<float *> &input) | |||||
| ++pos.r; // += delta.r; | ++pos.r; // += delta.r; | ||||
| //ensure that pos is still in bounds | //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 | //adjust delay if needed | ||||
| delta.l = (15 * delta.l + ndelta.l) / 16; | delta.l = (15 * delta.l + ndelta.l) / 16; | ||||
| @@ -30,7 +30,7 @@ | |||||
| class Echo:public Effect | class Echo:public Effect | ||||
| { | { | ||||
| public: | public: | ||||
| Echo(bool insertion_, float *efxoutl_, float *efxoutr_); | |||||
| Echo(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize); | |||||
| ~Echo(); | ~Echo(); | ||||
| void out(const Stereo<float *> &input); | void out(const Stereo<float *> &input); | ||||
| @@ -26,12 +26,15 @@ | |||||
| #include <cmath> | #include <cmath> | ||||
| Effect::Effect(bool insertion_, float *efxoutl_, float *efxoutr_, | 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_), | :Ppreset(Ppreset_), | ||||
| efxoutl(efxoutl_), | efxoutl(efxoutl_), | ||||
| efxoutr(efxoutr_), | efxoutr(efxoutr_), | ||||
| filterpars(filterpars_), | filterpars(filterpars_), | ||||
| insertion(insertion_) | |||||
| insertion(insertion_), | |||||
| samplerate(srate), | |||||
| buffersize(bufsize) | |||||
| {} | {} | ||||
| void Effect::out(float *const smpsl, float *const smpsr) | void Effect::out(float *const smpsl, float *const smpsr) | ||||
| @@ -24,7 +24,6 @@ | |||||
| #define EFFECT_H | #define EFFECT_H | ||||
| #include "../Misc/Util.h" | #include "../Misc/Util.h" | ||||
| #include "../globals.h" | |||||
| #include "../Params/FilterParams.h" | #include "../Params/FilterParams.h" | ||||
| #include "../Misc/Stereo.h" | #include "../Misc/Stereo.h" | ||||
| @@ -43,7 +42,8 @@ class Effect | |||||
| * @param Ppreset_ chosen preset | * @param Ppreset_ chosen preset | ||||
| * @return Initialized Effect object*/ | * @return Initialized Effect object*/ | ||||
| Effect(bool insertion_, float *efxoutl_, float *efxoutr_, | Effect(bool insertion_, float *efxoutl_, float *efxoutr_, | ||||
| FilterParams *filterpars_, unsigned char Ppreset_); | |||||
| FilterParams *filterpars_, unsigned char Ppreset_, | |||||
| unsigned int srate, int bufsize); | |||||
| virtual ~Effect() {} | virtual ~Effect() {} | ||||
| /** | /** | ||||
| * Choose a preset | * Choose a preset | ||||
| @@ -100,6 +100,10 @@ class Effect | |||||
| float pangainR; | float pangainR; | ||||
| char Plrcross; // L/R mix | char Plrcross; // L/R mix | ||||
| float lrcross; | float lrcross; | ||||
| // current setup | |||||
| unsigned int samplerate; | |||||
| int buffersize; | |||||
| }; | }; | ||||
| #endif | #endif | ||||
| @@ -25,7 +25,7 @@ | |||||
| #include <cmath> | #include <cmath> | ||||
| EffectLFO::EffectLFO(void) | |||||
| EffectLFO::EffectLFO(float srate, float bufsize) | |||||
| :Pfreq(40), | :Pfreq(40), | ||||
| Prandomness(0), | Prandomness(0), | ||||
| PLFOtype(0), | PLFOtype(0), | ||||
| @@ -36,7 +36,9 @@ EffectLFO::EffectLFO(void) | |||||
| ampl2(RND), | ampl2(RND), | ||||
| ampr1(RND), | ampr1(RND), | ||||
| ampr2(RND), | ampr2(RND), | ||||
| lfornd(0.0f) | |||||
| lfornd(0.0f), | |||||
| samplerate_f(srate), | |||||
| buffersize_f(bufsize) | |||||
| { | { | ||||
| updateparams(); | updateparams(); | ||||
| } | } | ||||
| @@ -47,7 +49,7 @@ EffectLFO::~EffectLFO() {} | |||||
| void EffectLFO::updateparams(void) | void EffectLFO::updateparams(void) | ||||
| { | { | ||||
| float lfofreq = (powf(2.0f, Pfreq / 127.0f * 10.0f) - 1.0f) * 0.03f; | 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) | if(incx > 0.49999999f) | ||||
| incx = 0.499999999f; //Limit the Frequency | incx = 0.499999999f; //Limit the Frequency | ||||
| @@ -28,7 +28,7 @@ | |||||
| class EffectLFO | class EffectLFO | ||||
| { | { | ||||
| public: | public: | ||||
| EffectLFO(); | |||||
| EffectLFO(float srate, float bufsize); | |||||
| ~EffectLFO(); | ~EffectLFO(); | ||||
| void effectlfoout(float *outl, float *outr); | void effectlfoout(float *outl, float *outr); | ||||
| void updateparams(void); | void updateparams(void); | ||||
| @@ -45,6 +45,9 @@ class EffectLFO | |||||
| float lfointensity; | float lfointensity; | ||||
| float lfornd; | float lfornd; | ||||
| char lfotype; | char lfotype; | ||||
| float samplerate_f; | |||||
| float buffersize_f; | |||||
| }; | }; | ||||
| #endif | #endif | ||||
| @@ -76,28 +76,28 @@ void EffectMgr::changeeffect(int _nefx) | |||||
| delete efx; | delete efx; | ||||
| switch(nefx) { | switch(nefx) { | ||||
| case 1: | case 1: | ||||
| efx = new Reverb(insertion, efxoutl, efxoutr); | |||||
| efx = new Reverb(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize); | |||||
| break; | break; | ||||
| case 2: | case 2: | ||||
| efx = new Echo(insertion, efxoutl, efxoutr); | |||||
| efx = new Echo(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize); | |||||
| break; | break; | ||||
| case 3: | case 3: | ||||
| efx = new Chorus(insertion, efxoutl, efxoutr); | |||||
| efx = new Chorus(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize); | |||||
| break; | break; | ||||
| case 4: | case 4: | ||||
| efx = new Phaser(insertion, efxoutl, efxoutr); | |||||
| efx = new Phaser(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize); | |||||
| break; | break; | ||||
| case 5: | case 5: | ||||
| efx = new Alienwah(insertion, efxoutl, efxoutr); | |||||
| efx = new Alienwah(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize); | |||||
| break; | break; | ||||
| case 6: | case 6: | ||||
| efx = new Distorsion(insertion, efxoutl, efxoutr); | |||||
| efx = new Distorsion(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize); | |||||
| break; | break; | ||||
| case 7: | case 7: | ||||
| efx = new EQ(insertion, efxoutl, efxoutr); | |||||
| efx = new EQ(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize); | |||||
| break; | break; | ||||
| case 8: | case 8: | ||||
| efx = new DynamicFilter(insertion, efxoutl, efxoutr); | |||||
| efx = new DynamicFilter(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize); | |||||
| break; | break; | ||||
| //put more effect here | //put more effect here | ||||
| default: | default: | ||||
| @@ -39,8 +39,8 @@ using namespace std; | |||||
| #define ONE_ 0.99999f // To prevent LFO ever reaching 1.0f for filter stability purposes | #define ONE_ 0.99999f // To prevent LFO ever reaching 1.0f for filter stability purposes | ||||
| #define ZERO_ 0.00001f // Same idea as above. | #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) | yn1(NULL), diff(0.0f), oldgain(0.0f), fb(0.0f) | ||||
| { | { | ||||
| analog_setup(); | analog_setup(); | ||||
| @@ -72,8 +72,8 @@ void Phaser::analog_setup() | |||||
| Rmx = Rmin / Rmax; | Rmx = Rmin / Rmax; | ||||
| Rconst = 1.0f + Rmx; // Handle parallel resistor relationship | Rconst = 1.0f + Rmx; // Handle parallel resistor relationship | ||||
| C = 0.00000005f; // 50 nF | 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() | Phaser::~Phaser() | ||||
| @@ -129,7 +129,7 @@ void Phaser::AnalogPhase(const Stereo<float *> &input) | |||||
| g = oldgain; | g = oldgain; | ||||
| oldgain = mod; | 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.l += diff.l; // Linear interpolation between LFO samples | ||||
| g.r += diff.r; | g.r += diff.r; | ||||
| @@ -151,8 +151,8 @@ void Phaser::AnalogPhase(const Stereo<float *> &input) | |||||
| } | } | ||||
| if(Poutsub) { | 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<float *> &input) | |||||
| gain.l = limit(gain.l, ZERO_, ONE_); | gain.l = limit(gain.l, ZERO_, ONE_); | ||||
| gain.r = limit(gain.r, 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; | float x1 = 1.0f - x; | ||||
| //TODO think about making panning an external feature | //TODO think about making panning an external feature | ||||
| Stereo<float> xn(input.l[i] * pangainL + fb.l, | Stereo<float> xn(input.l[i] * pangainL + fb.l, | ||||
| @@ -227,8 +227,8 @@ void Phaser::normalPhase(const Stereo<float *> &input) | |||||
| oldgain = gain; | oldgain = gain; | ||||
| if(Poutsub) { | if(Poutsub) { | ||||
| invSignal(efxoutl, synth->buffersize); | |||||
| invSignal(efxoutr, synth->buffersize); | |||||
| invSignal(efxoutl, buffersize); | |||||
| invSignal(efxoutr, buffersize); | |||||
| } | } | ||||
| } | } | ||||
| @@ -35,7 +35,7 @@ | |||||
| class Phaser:public Effect | class Phaser:public Effect | ||||
| { | { | ||||
| public: | public: | ||||
| Phaser(const int &insertion_, float *efxoutl_, float *efxoutr_); | |||||
| Phaser(const int &insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize); | |||||
| ~Phaser(); | ~Phaser(); | ||||
| void out(const Stereo<float *> &input); | void out(const Stereo<float *> &input); | ||||
| void setpreset(unsigned char npreset); | void setpreset(unsigned char npreset); | ||||
| @@ -28,8 +28,8 @@ | |||||
| //todo: EarlyReflections, Prdelay, Perbalance | //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 | // defaults | ||||
| Pvolume(48), | Pvolume(48), | ||||
| Ptime(64), | Ptime(64), | ||||
| @@ -116,7 +116,7 @@ void Reverb::processmono(int ch, float *output, float *inputbuf) | |||||
| const int comblength = comblen[j]; | const int comblength = comblen[j]; | ||||
| float &lpcombj = lpcomb[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]; | float fbout = comb[j][ck] * combfb[j]; | ||||
| fbout = fbout * (1.0f - lohifb) + lpcombj * lohifb; | fbout = fbout * (1.0f - lohifb) + lpcombj * lohifb; | ||||
| lpcombj = fbout; | 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) { | for(int j = REV_APS * ch; j < REV_APS * (1 + ch); ++j) { | ||||
| int &ak = apk[j]; | int &ak = apk[j]; | ||||
| const int aplength = aplen[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]; | float tmp = ap[j][ak]; | ||||
| ap[j][ak] = 0.7f * tmp + output[i]; | ap[j][ak] = 0.7f * tmp + output[i]; | ||||
| output[i] = tmp - 0.7f * ap[j][ak]; | output[i] = tmp - 0.7f * ap[j][ak]; | ||||
| @@ -149,11 +149,11 @@ void Reverb::out(const Stereo<float *> &smp) | |||||
| return; | return; | ||||
| float *inputbuf = getTmpBuffer(); | 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; | inputbuf[i] = (smp.l[i] + smp.r[i]) / 2.0f; | ||||
| if(idelay) | if(idelay) | ||||
| for(int i = 0; i < synth->buffersize; ++i) { | |||||
| for(int i = 0; i < buffersize; ++i) { | |||||
| //Initial delay r | //Initial delay r | ||||
| float tmp = inputbuf[i] + idelay[idelayk] * idelayfb; | float tmp = inputbuf[i] + idelay[idelayk] * idelayfb; | ||||
| inputbuf[i] = idelay[idelayk]; | inputbuf[i] = idelay[idelayk]; | ||||
| @@ -164,7 +164,7 @@ void Reverb::out(const Stereo<float *> &smp) | |||||
| } | } | ||||
| if(bandwidth) | if(bandwidth) | ||||
| bandwidth->process(synth->buffersize, inputbuf); | |||||
| bandwidth->process(buffersize, inputbuf); | |||||
| if(lpf) | if(lpf) | ||||
| lpf->filterout(inputbuf); | lpf->filterout(inputbuf); | ||||
| @@ -181,7 +181,7 @@ void Reverb::out(const Stereo<float *> &smp) | |||||
| lvol *= 2.0f; | lvol *= 2.0f; | ||||
| rvol *= 2.0f; | rvol *= 2.0f; | ||||
| } | } | ||||
| for(int i = 0; i < synth->buffersize; ++i) { | |||||
| for(int i = 0; i < buffersize; ++i) { | |||||
| efxoutl[i] *= lvol; | efxoutl[i] *= lvol; | ||||
| efxoutr[i] *= rvol; | efxoutr[i] *= rvol; | ||||
| } | } | ||||
| @@ -210,7 +210,7 @@ void Reverb::settime(unsigned char _Ptime) | |||||
| for(int i = 0; i < REV_COMBS * 2; ++i) | for(int i = 0; i < REV_COMBS * 2; ++i) | ||||
| combfb[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 | //the feedback is negative because it removes the DC | ||||
| } | } | ||||
| @@ -241,7 +241,7 @@ void Reverb::setidelay(unsigned char _Pidelay) | |||||
| delete [] idelay; | delete [] idelay; | ||||
| idelay = NULL; | idelay = NULL; | ||||
| idelaylen = (int) (synth->samplerate_f * delay / 1000); | |||||
| idelaylen = (int) ((float)samplerate * delay / 1000.0f); | |||||
| if(idelaylen > 1) { | if(idelaylen > 1) { | ||||
| idelayk = 0; | idelayk = 0; | ||||
| idelay = new float[idelaylen]; | idelay = new float[idelaylen]; | ||||
| @@ -266,7 +266,7 @@ void Reverb::sethpf(unsigned char _Phpf) | |||||
| else { | else { | ||||
| float fr = expf(powf(Phpf / 127.0f, 0.5f) * logf(10000.0f)) + 20.0f; | float fr = expf(powf(Phpf / 127.0f, 0.5f) * logf(10000.0f)) + 20.0f; | ||||
| if(hpf == NULL) | if(hpf == NULL) | ||||
| hpf = new AnalogFilter(3, fr, 1, 0); | |||||
| hpf = new AnalogFilter(3, fr, 1, 0, samplerate, buffersize); | |||||
| else | else | ||||
| hpf->setfreq(fr); | hpf->setfreq(fr); | ||||
| } | } | ||||
| @@ -283,7 +283,7 @@ void Reverb::setlpf(unsigned char _Plpf) | |||||
| else { | else { | ||||
| float fr = expf(powf(Plpf / 127.0f, 0.5f) * logf(25000.0f)) + 40.0f; | float fr = expf(powf(Plpf / 127.0f, 0.5f) * logf(25000.0f)) + 40.0f; | ||||
| if(!lpf) | if(!lpf) | ||||
| lpf = new AnalogFilter(2, fr, 1, 0); | |||||
| lpf = new AnalogFilter(2, fr, 1, 0, samplerate, buffersize); | |||||
| else | else | ||||
| lpf->setfreq(fr); | lpf->setfreq(fr); | ||||
| } | } | ||||
| @@ -315,7 +315,7 @@ void Reverb::settype(unsigned char _Ptype) | |||||
| Ptype = NUM_TYPES - 1; | Ptype = NUM_TYPES - 1; | ||||
| // adjust the combs according to the samplerate | // adjust the combs according to the samplerate | ||||
| float samplerate_adjust = synth->samplerate_f / 44100.0f; | |||||
| float samplerate_adjust = (float)samplerate / 44100.0f; | |||||
| float tmp; | float tmp; | ||||
| for(int i = 0; i < REV_COMBS * 2; ++i) { | for(int i = 0; i < REV_COMBS * 2; ++i) { | ||||
| if(Ptype == 0) | if(Ptype == 0) | ||||
| @@ -360,7 +360,7 @@ void Reverb::settype(unsigned char _Ptype) | |||||
| //not been verified yet. | //not been verified yet. | ||||
| //As this cannot be resized in a RT context, a good upper bound should | //As this cannot be resized in a RT context, a good upper bound should | ||||
| //be found | //be found | ||||
| bandwidth = new Unison(synth->buffersize / 4 + 1, 2.0f); | |||||
| bandwidth = new Unison(buffersize / 4 + 1, 2.0f); | |||||
| bandwidth->setSize(50); | bandwidth->setSize(50); | ||||
| bandwidth->setBaseFrequency(1.0f); | bandwidth->setBaseFrequency(1.0f); | ||||
| } | } | ||||
| @@ -32,7 +32,7 @@ | |||||
| class Reverb:public Effect | class Reverb:public Effect | ||||
| { | { | ||||
| public: | public: | ||||
| Reverb(bool insertion_, float *efxoutl_, float *efxoutr_); | |||||
| Reverb(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize); | |||||
| ~Reverb(); | ~Reverb(); | ||||
| void out(const Stereo<float *> &smp); | void out(const Stereo<float *> &smp); | ||||
| void cleanup(void); | void cleanup(void); | ||||
| @@ -45,7 +45,7 @@ endif | |||||
| # -------------------------------------------------------------- | # -------------------------------------------------------------- | ||||
| # Native | # Native | ||||
| DGL_LIBS = -lX11 | |||||
| DGL_LIBS = -lX11 -lXext | |||||
| ifeq ($(HAVE_OPENGL),true) | ifeq ($(HAVE_OPENGL),true) | ||||
| LINK_FLAGS += $(shell pkg-config --libs gl) $(DGL_LIBS) | LINK_FLAGS += $(shell pkg-config --libs gl) $(DGL_LIBS) | ||||
| @@ -76,6 +76,10 @@ LINK_FLAGS += $(EXTRA_LIBS) | |||||
| LIBS = ../modules/carla_native.a | LIBS = ../modules/carla_native.a | ||||
| LIBS += ../modules/juce_audio_basics.a | LIBS += ../modules/juce_audio_basics.a | ||||
| LIBS += ../modules/juce_core.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 | LIBS += ../modules/rtmempool.a | ||||
| # ifeq ($(CARLA_PLUGIN_SUPPORT),true) | # ifeq ($(CARLA_PLUGIN_SUPPORT),true) | ||||
| @@ -143,7 +147,7 @@ carla-native-lv2-export.exe: carla-native-lv2-export.cpp.o $(LIBS) | |||||
| # -------------------------------------------------------------- | # -------------------------------------------------------------- | ||||
| .FORCE: | .FORCE: | ||||
| .PHONY: .FORCE | |||||
| .PHONY: .FORCE carla-native-lv2-export carla-native-lv2-export.exe | |||||
| ../modules/%.a: .FORCE | ../modules/%.a: .FORCE | ||||
| $(MAKE) -C ../modules $* | $(MAKE) -C ../modules $* | ||||
| @@ -35,7 +35,8 @@ void carla_register_native_plugin_midiTranspose(); | |||||
| void carla_register_native_plugin_nekofilter(); | void carla_register_native_plugin_nekofilter(); | ||||
| // Simple plugins (C++) | // 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 | #ifdef WANT_AUDIOFILE | ||||
| // AudioFile | // AudioFile | ||||
| @@ -63,7 +64,8 @@ void carla_register_native_plugin_Notes(); | |||||
| #ifdef WANT_ZYNADDSUBFX | #ifdef WANT_ZYNADDSUBFX | ||||
| // ZynAddSubFX | // ZynAddSubFX | ||||
| void carla_register_native_plugin_zynaddsubfx(); | |||||
| void carla_register_native_plugin_zynaddsubfx_fx(); | |||||
| void carla_register_native_plugin_zynaddsubfx_synth(); | |||||
| #endif | #endif | ||||
| } | } | ||||
| @@ -83,7 +85,8 @@ struct PluginListManager { | |||||
| carla_register_native_plugin_nekofilter(); | carla_register_native_plugin_nekofilter(); | ||||
| // Simple plugins (C++) | // Simple plugins (C++) | ||||
| carla_register_native_plugin_vex(); | |||||
| carla_register_native_plugin_vex_fx(); | |||||
| carla_register_native_plugin_vex_synth(); | |||||
| #ifdef WANT_AUDIOFILE | #ifdef WANT_AUDIOFILE | ||||
| // AudioFile | // AudioFile | ||||
| @@ -111,7 +114,8 @@ struct PluginListManager { | |||||
| #ifdef WANT_ZYNADDSUBFX | #ifdef WANT_ZYNADDSUBFX | ||||
| // ZynAddSubFX | // ZynAddSubFX | ||||
| carla_register_native_plugin_zynaddsubfx(); | |||||
| carla_register_native_plugin_zynaddsubfx_fx(); | |||||
| carla_register_native_plugin_zynaddsubfx_synth(); | |||||
| #endif | #endif | ||||
| } | } | ||||