| @@ -32,7 +32,8 @@ void carla_register_native_plugin_midiThrough(); | |||
| void carla_register_native_plugin_midiTranspose(); | |||
| void carla_register_native_plugin_nekofilter(); | |||
| void carla_register_native_plugin_sunvoxfile(); | |||
| void carla_register_native_plugin_vex(); | |||
| void carla_register_native_plugin_vex_fx(); | |||
| void carla_register_native_plugin_vex_synth(); | |||
| #ifndef BUILD_BRIDGE | |||
| // Carla | |||
| @@ -65,7 +66,8 @@ void carla_register_native_plugin_Notes(); | |||
| #ifdef WANT_ZYNADDSUBFX | |||
| // ZynAddSubFX | |||
| void carla_register_native_plugin_zynaddsubfx(); | |||
| void carla_register_native_plugin_zynaddsubfx_fx(); | |||
| void carla_register_native_plugin_zynaddsubfx_synth(); | |||
| #endif | |||
| } | |||
| @@ -80,7 +82,8 @@ void carla_register_all_plugins() | |||
| carla_register_native_plugin_midiTranspose(); | |||
| carla_register_native_plugin_nekofilter(); | |||
| //carla_register_native_plugin_sunvoxfile(); // unfinished | |||
| carla_register_native_plugin_vex(); | |||
| carla_register_native_plugin_vex_fx(); | |||
| carla_register_native_plugin_vex_synth(); | |||
| #ifndef BUILD_BRIDGE | |||
| // Carla | |||
| @@ -113,7 +116,8 @@ void carla_register_all_plugins() | |||
| #ifdef WANT_ZYNADDSUBFX | |||
| // ZynAddSubFX | |||
| carla_register_native_plugin_zynaddsubfx(); | |||
| carla_register_native_plugin_zynaddsubfx_fx(); | |||
| carla_register_native_plugin_zynaddsubfx_synth(); | |||
| #endif | |||
| } | |||
| @@ -55,7 +55,8 @@ OBJS = \ | |||
| # Simple plugins (C++) | |||
| OBJS += \ | |||
| vex.cpp.o \ | |||
| vex-fx.cpp.o \ | |||
| vex-synth.cpp.o \ | |||
| vex-src.cpp.o | |||
| # AudioFile | |||
| @@ -92,7 +93,8 @@ OBJS += \ | |||
| ifeq ($(HAVE_ZYN_DEPS),true) | |||
| # ZynAddSubFX | |||
| OBJS += \ | |||
| zynaddsubfx.cpp.o \ | |||
| zynaddsubfx-fx.cpp.o \ | |||
| zynaddsubfx-synth.cpp.o \ | |||
| zynaddsubfx-src.cpp.o | |||
| ifeq ($(HAVE_ZYN_UI_DEPS),true) | |||
| @@ -199,13 +201,10 @@ midi-sequencer.cpp.o: midi-sequencer.cpp midi-base.hpp $(CXXDEPS) | |||
| nekofilter.c.o: nekofilter.c nekofilter/*.c nekofilter/*.h $(CDEPS) | |||
| $(CC) $< $(BUILD_C_FLAGS) -c -o $@ | |||
| zynaddsubfx.cpp.o: zynaddsubfx.cpp $(CXXDEPS) $(ZYN_UI_FILES_H) | |||
| $(CXX) $< $(ZYN_CXX_FLAGS) -c -o $@ | |||
| zynaddsubfx-src.cpp.o: zynaddsubfx-src.cpp $(ZYN_UI_FILES_H) | |||
| zynaddsubfx-ui.cpp.o: zynaddsubfx-ui.cpp $(ZYN_UI_FILES_H) $(ZYN_UI_FILES_CPP) | |||
| $(CXX) $< $(ZYN_CXX_FLAGS) -c -o $@ | |||
| zynaddsubfx-ui.cpp.o: zynaddsubfx-ui.cpp $(ZYN_UI_FILES_H) $(ZYN_UI_FILES_CPP) | |||
| zynaddsubfx-%.cpp.o: zynaddsubfx-%.cpp $(CXXDEPS) $(ZYN_UI_FILES_H) | |||
| $(CXX) $< $(ZYN_CXX_FLAGS) -c -o $@ | |||
| zynaddsubfx/UI/%.cpp: zynaddsubfx/UI/%.fl | |||
| @@ -17,7 +17,7 @@ | |||
| #include "CarlaNative.hpp" | |||
| #include "juce_core.h" | |||
| #include "juce_gui_basics.h" | |||
| using namespace juce; | |||
| @@ -25,13 +25,8 @@ using namespace juce; | |||
| #include "vex/VexChorus.h" | |||
| #include "vex/VexDelay.h" | |||
| #include "vex/VexReverb.h" | |||
| #include "vex/VexSyntModule.h" | |||
| #include "vex/PeggyViewComponent.h" | |||
| #include "vex/lookandfeel/MyLookAndFeel.h" | |||
| #include "vex/resources/Resources.h" | |||
| #include "vex/resources/Resources.cpp" | |||
| // ----------------------------------------------------------------------- | |||
| @@ -96,139 +91,6 @@ private: | |||
| // ----------------------------------------------------------------------- | |||
| class VexEditorComponent : public ComboBox::Listener, | |||
| public Slider::Listener, | |||
| public Button::Listener, | |||
| public ChangeListener, | |||
| public Component, | |||
| public PeggyViewComponent::Callback | |||
| { | |||
| public: | |||
| VexEditorComponent() | |||
| { | |||
| internalCachedImage1 = ImageCache::getFromMemory(Resources::vex3_png, Resources::vex3_pngSize); | |||
| // Comboboxes, wave selection | |||
| addAndMakeVisible(comboBox1 = new ComboBox (String::empty)); | |||
| comboBox1->setEditableText(false); | |||
| comboBox1->setJustificationType(Justification::centredLeft); | |||
| comboBox1->setTextWhenNothingSelected(String("silent")); | |||
| comboBox1->setTextWhenNoChoicesAvailable(String("silent")); | |||
| comboBox1->addListener(this); | |||
| comboBox1->setColour(ComboBox::backgroundColourId, Colours::black); | |||
| comboBox1->setColour(ComboBox::textColourId, Colours::lightgrey); | |||
| comboBox1->setColour(ComboBox::outlineColourId, Colours::grey); | |||
| comboBox1->setColour(ComboBox::buttonColourId, Colours::grey); | |||
| comboBox1->setWantsKeyboardFocus(false); | |||
| comboBox1->setLookAndFeel(&mlaf); | |||
| addAndMakeVisible (comboBox2 = new ComboBox (String::empty)); | |||
| comboBox2->setEditableText (false); | |||
| comboBox2->setJustificationType (Justification::centredLeft); | |||
| comboBox2->setTextWhenNothingSelected (String("silent")); | |||
| comboBox2->setTextWhenNoChoicesAvailable (String("silent")); | |||
| comboBox2->addListener (this); | |||
| comboBox2->setColour(ComboBox::backgroundColourId, Colours::black); | |||
| comboBox2->setColour(ComboBox::textColourId, Colours::lightgrey); | |||
| comboBox2->setColour(ComboBox::outlineColourId, Colours::grey); | |||
| comboBox2->setColour(ComboBox::buttonColourId, Colours::grey); | |||
| comboBox2->setWantsKeyboardFocus(false); | |||
| comboBox2->setLookAndFeel(&mlaf); | |||
| addAndMakeVisible (comboBox3 = new ComboBox (String::empty)); | |||
| comboBox3->setEditableText (false); | |||
| comboBox3->setJustificationType (Justification::centredLeft); | |||
| comboBox3->setTextWhenNothingSelected (String("silent")); | |||
| comboBox3->setTextWhenNoChoicesAvailable (String("silent")); | |||
| comboBox3->addListener (this); | |||
| comboBox3->setColour(ComboBox::backgroundColourId, Colours::black); | |||
| comboBox3->setColour(ComboBox::textColourId, Colours::lightgrey); | |||
| comboBox3->setColour(ComboBox::outlineColourId, Colours::grey); | |||
| comboBox3->setColour(ComboBox::buttonColourId, Colours::grey); | |||
| comboBox3->setWantsKeyboardFocus(false); | |||
| comboBox3->setLookAndFeel(&mlaf); | |||
| for (int i = 0, tableSize = WaveRenderer::getWaveTableSize(); i < tableSize; ++i) | |||
| { | |||
| String tableName(WaveRenderer::getWaveTableName(i)); | |||
| comboBox1->addItem(tableName, i + 1); | |||
| comboBox2->addItem(tableName, i + 1); | |||
| comboBox3->addItem(tableName, i + 1); | |||
| } | |||
| addChildComponent(p1 = new PeggyViewComponent(1, _d, this)); | |||
| p1->setLookAndFeel(&mlaf); | |||
| addChildComponent(p2 = new PeggyViewComponent(2, _d, this)); | |||
| p2->setLookAndFeel(&mlaf); | |||
| addChildComponent(p3 = new PeggyViewComponent(3, _d, this)); | |||
| p3->setLookAndFeel(&mlaf); | |||
| //ownerFilter->addChangeListener (this); | |||
| setSize(800,500); | |||
| } | |||
| ~VexEditorComponent() | |||
| { | |||
| removeAllChildren(); | |||
| } | |||
| protected: | |||
| void paint(Graphics& g) override | |||
| { | |||
| g.drawImage(internalCachedImage1, | |||
| 0, 0, 800, 500, | |||
| 0, 0, internalCachedImage1.getWidth(), internalCachedImage1.getHeight()); | |||
| } | |||
| void resized() override | |||
| { | |||
| comboBox1->setBounds(13, 38, 173, 23); | |||
| comboBox2->setBounds(213, 38, 173, 23); | |||
| comboBox3->setBounds(413, 38, 173, 23); | |||
| p1->setBounds(10, 20, 207, 280); | |||
| p2->setBounds(210, 20, 207, 280); | |||
| p3->setBounds(410, 20, 207, 280); | |||
| } | |||
| void changeListenerCallback(ChangeBroadcaster* source) override | |||
| { | |||
| } | |||
| void comboBoxChanged(ComboBox* comboBoxThatHasChanged) override | |||
| { | |||
| } | |||
| void sliderValueChanged(Slider* sliderThatWasMoved) override | |||
| { | |||
| } | |||
| void buttonClicked(Button* buttonThatWasClicked) override | |||
| { | |||
| } | |||
| void somethingChanged(const uint32_t id) override | |||
| { | |||
| } | |||
| private: | |||
| Image internalCachedImage1; | |||
| MyLookAndFeel mlaf; | |||
| ScopedPointer<ComboBox> comboBox1; | |||
| ScopedPointer<ComboBox> comboBox2; | |||
| ScopedPointer<ComboBox> comboBox3; | |||
| ScopedPointer<PeggyViewComponent> p1; | |||
| ScopedPointer<PeggyViewComponent> p2; | |||
| ScopedPointer<PeggyViewComponent> p3; | |||
| VexArpSettings _d; | |||
| }; | |||
| // ----------------------------------------------------------------------- | |||
| class VexArpPlugin : public PluginClass, | |||
| public PeggyViewComponent::Callback | |||
| { | |||
| @@ -1009,469 +871,6 @@ private: | |||
| // ----------------------------------------------------------------------- | |||
| class VexSynthPlugin : public PluginClass | |||
| { | |||
| public: | |||
| static const unsigned int kParamCount = 92; | |||
| VexSynthPlugin(const HostDescriptor* const host) | |||
| : PluginClass(host), | |||
| obf(nullptr), | |||
| abf(nullptr), | |||
| dbf1(nullptr), | |||
| dbf2(nullptr), | |||
| dbf3(nullptr), | |||
| fChorus(fParameters), | |||
| fDelay(fParameters), | |||
| fReverb(fParameters), | |||
| fSynth(fParameters) | |||
| { | |||
| std::memset(fParameters, 0, sizeof(float)*92); | |||
| fParameters[0] = 1.0f; // main volume | |||
| for (int i = 0; i < 3; ++i) | |||
| { | |||
| const int offset = i * 24; | |||
| fParameters[offset + 1] = 0.5f; | |||
| fParameters[offset + 2] = 0.5f; | |||
| fParameters[offset + 3] = 0.5f; | |||
| fParameters[offset + 4] = 0.5f; | |||
| fParameters[offset + 5] = 0.9f; | |||
| fParameters[offset + 6] = 0.0f; | |||
| fParameters[offset + 7] = 1.0f; | |||
| fParameters[offset + 8] = 0.5f; | |||
| fParameters[offset + 9] = 0.0f; | |||
| fParameters[offset + 10] = 0.2f; | |||
| fParameters[offset + 11] = 0.0f; | |||
| fParameters[offset + 12] = 0.5f; | |||
| fParameters[offset + 13] = 0.5f; | |||
| fParameters[offset + 14] = 0.0f; | |||
| fParameters[offset + 15] = 0.3f; | |||
| fParameters[offset + 16] = 0.7f; | |||
| fParameters[offset + 17] = 0.1f; | |||
| fParameters[offset + 18] = 0.5f; | |||
| fParameters[offset + 19] = 0.5f; | |||
| fParameters[offset + 20] = 0.0f; | |||
| fParameters[offset + 21] = 0.0f; | |||
| fParameters[offset + 22] = 0.5f; | |||
| fParameters[offset + 23] = 0.5f; | |||
| fParameters[offset + 24] = 0.5f; | |||
| } | |||
| // ^1 - 72 | |||
| fParameters[73] = 0.5f; // Delay Time | |||
| fParameters[74] = 0.4f; // Delay Feedback | |||
| fParameters[75] = 0.0f; // Delay Volume | |||
| fParameters[76] = 0.3f; // Chorus Rate | |||
| fParameters[77] = 0.6f; // Chorus Depth | |||
| fParameters[78] = 0.5f; // Chorus Volume | |||
| fParameters[79] = 0.6f; // Reverb Size | |||
| fParameters[80] = 0.7f; // Reverb Width | |||
| fParameters[81] = 0.6f; // Reverb Damp | |||
| fParameters[82] = 0.0f; // Reverb Volume | |||
| fParameters[83] = 0.5f; // wave1 panning | |||
| fParameters[84] = 0.5f; // wave2 panning | |||
| fParameters[85] = 0.5f; // wave3 panning | |||
| fParameters[86] = 0.5f; // wave1 volume | |||
| fParameters[87] = 0.5f; // wave2 volume | |||
| fParameters[88] = 0.5f; // wave3 volume | |||
| fParameters[89] = 1.0f; // wave1 on/off | |||
| fParameters[90] = 1.0f; // wave2 on/off | |||
| fParameters[91] = 1.0f; // wave3 on/off | |||
| bufferSizeChanged(getBufferSize()); | |||
| sampleRateChanged(getSampleRate()); | |||
| } | |||
| ~VexSynthPlugin() | |||
| { | |||
| delete obf; | |||
| delete abf; | |||
| delete dbf1; | |||
| delete dbf2; | |||
| delete dbf3; | |||
| } | |||
| protected: | |||
| // ------------------------------------------------------------------- | |||
| // Plugin parameter calls | |||
| uint32_t getParameterCount() const override | |||
| { | |||
| return kParamCount; | |||
| } | |||
| const Parameter* getParameterInfo(const uint32_t index) const override | |||
| { | |||
| static Parameter paramInfo; | |||
| int hints = PARAMETER_IS_ENABLED|PARAMETER_IS_AUTOMABLE; | |||
| paramInfo.name = nullptr; | |||
| paramInfo.unit = nullptr; | |||
| paramInfo.ranges.def = 0.0f; | |||
| paramInfo.ranges.min = 0.0f; | |||
| paramInfo.ranges.max = 1.0f; | |||
| paramInfo.ranges.step = PARAMETER_RANGES_DEFAULT_STEP; | |||
| paramInfo.ranges.stepSmall = PARAMETER_RANGES_DEFAULT_STEP_SMALL; | |||
| paramInfo.ranges.stepLarge = PARAMETER_RANGES_DEFAULT_STEP_LARGE; | |||
| paramInfo.scalePointCount = 0; | |||
| paramInfo.scalePoints = nullptr; | |||
| if (index >= 1 && index <= 72) | |||
| { | |||
| uint32_t ri = index % 24; | |||
| switch (ri) | |||
| { | |||
| case 1: | |||
| paramInfo.name = "oct"; | |||
| break; | |||
| case 2: | |||
| paramInfo.name = "cent"; | |||
| break; | |||
| case 3: | |||
| paramInfo.name = "phaseOffset"; | |||
| break; | |||
| case 4: | |||
| paramInfo.name = "phaseIncOffset"; | |||
| break; | |||
| case 5: | |||
| paramInfo.name = "filter"; | |||
| break; | |||
| case 6: | |||
| paramInfo.name = "filter"; | |||
| break; | |||
| case 7: | |||
| paramInfo.name = "filter"; | |||
| break; | |||
| case 8: | |||
| paramInfo.name = "filter"; | |||
| break; | |||
| case 9: | |||
| paramInfo.name = "F ADSR"; | |||
| break; | |||
| case 10: | |||
| paramInfo.name = "F ADSR"; | |||
| break; | |||
| case 11: | |||
| paramInfo.name = "F ADSR"; | |||
| break; | |||
| case 12: | |||
| paramInfo.name = "F ADSR"; | |||
| break; | |||
| case 13: | |||
| paramInfo.name = "F velocity"; | |||
| break; | |||
| case 14: | |||
| paramInfo.name = "A ADSR"; | |||
| break; | |||
| case 15: | |||
| paramInfo.name = "A ADSR"; | |||
| break; | |||
| case 16: | |||
| paramInfo.name = "A ADSR"; | |||
| break; | |||
| case 17: | |||
| paramInfo.name = "A ADSR"; | |||
| break; | |||
| case 18: | |||
| paramInfo.name = "A velocity"; | |||
| break; | |||
| case 19: | |||
| paramInfo.name = "lfoC"; | |||
| break; | |||
| case 20: | |||
| paramInfo.name = "lfoA"; | |||
| break; | |||
| case 21: | |||
| paramInfo.name = "lfoF"; | |||
| break; | |||
| case 22: | |||
| paramInfo.name = "fx vol D"; | |||
| break; | |||
| case 23: | |||
| paramInfo.name = "fx vol C"; | |||
| break; | |||
| case 24: | |||
| case 0: | |||
| paramInfo.name = "fx vol R"; | |||
| break; | |||
| default: | |||
| paramInfo.name = "unknown2"; | |||
| break; | |||
| } | |||
| paramInfo.hints = static_cast<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 = { | |||
| /* category */ PLUGIN_CATEGORY_UTILITY, | |||
| /* hints */ static_cast<PluginHints>(PLUGIN_HAS_GUI|PLUGIN_NEEDS_SINGLE_THREAD|PLUGIN_USES_TIME), | |||
| @@ -1540,33 +939,15 @@ static const PluginDescriptor vexReverbDesc = { | |||
| PluginDescriptorFILL(VexReverbPlugin) | |||
| }; | |||
| static const PluginDescriptor vexSynthDesc = { | |||
| /* category */ PLUGIN_CATEGORY_SYNTH, | |||
| /* hints */ static_cast<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() | |||
| void carla_register_native_plugin_vex_fx() | |||
| { | |||
| carla_register_native_plugin(&vexArpDesc); | |||
| carla_register_native_plugin(&vexChorusDesc); | |||
| carla_register_native_plugin(&vexDelayDesc); | |||
| carla_register_native_plugin(&vexReverbDesc); | |||
| carla_register_native_plugin(&vexSynthDesc); | |||
| } | |||
| // ----------------------------------------------------------------------- | |||
| @@ -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/SUBnote.cpp" | |||
| #include "zynaddsubfx/Synth/SynthNote.cpp" | |||
| // Dummy variables and functions for linking purposes | |||
| const char* instance_name = nullptr; | |||
| SYNTH_T* synth = nullptr; | |||
| class WavFile; | |||
| namespace Nio { | |||
| bool start(void){return 1;} | |||
| void stop(void){} | |||
| bool setSource(std::string){return true;} | |||
| bool setSink(std::string){return true;} | |||
| std::set<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, | |||
| float Ffreq, | |||
| float Fq, | |||
| unsigned char Fstages) | |||
| unsigned char Fstages, | |||
| float srate, int bufsize) | |||
| :type(Ftype), | |||
| stages(Fstages), | |||
| freq(Ffreq), | |||
| q(Fq), | |||
| gain(1.0), | |||
| abovenq(false), | |||
| oldabovenq(false) | |||
| oldabovenq(false), | |||
| samplerate_f(srate), | |||
| halfsamplerate_f(srate/2.0f), | |||
| buffersize(bufsize), | |||
| buffersize_f(bufsize) | |||
| { | |||
| for(int i = 0; i < 3; ++i) | |||
| coeff.c[i] = coeff.d[i] = oldCoeff.c[i] = oldCoeff.d[i] = 0.0f; | |||
| @@ -74,8 +79,8 @@ void AnalogFilter::computefiltercoefs(void) | |||
| //do not allow frequencies bigger than samplerate/2 | |||
| float freq = this->freq; | |||
| if(freq > (synth->halfsamplerate_f - 500.0f)) { | |||
| freq = synth->halfsamplerate_f - 500.0f; | |||
| if(freq > (halfsamplerate_f - 500.0f)) { | |||
| freq = halfsamplerate_f - 500.0f; | |||
| zerocoefs = true; | |||
| } | |||
| if(freq < 0.1f) | |||
| @@ -98,7 +103,7 @@ void AnalogFilter::computefiltercoefs(void) | |||
| float *d = coeff.d; | |||
| //General Constants | |||
| const float omega = 2 * PI * freq / synth->samplerate_f; | |||
| const float omega = 2 * PI * freq / samplerate_f; | |||
| const float sn = sinf(omega), cs = cosf(omega); | |||
| float alpha, beta; | |||
| @@ -109,7 +114,7 @@ void AnalogFilter::computefiltercoefs(void) | |||
| switch(type) { | |||
| case 0: //LPF 1 pole | |||
| if(!zerocoefs) | |||
| tmp = expf(-2.0f * PI * freq / synth->samplerate_f); | |||
| tmp = expf(-2.0f * PI * freq / samplerate_f); | |||
| else | |||
| tmp = 0.0f; | |||
| c[0] = 1.0f - tmp; | |||
| @@ -121,7 +126,7 @@ void AnalogFilter::computefiltercoefs(void) | |||
| break; | |||
| case 1: //HPF 1 pole | |||
| if(!zerocoefs) | |||
| tmp = expf(-2.0f * PI * freq / synth->samplerate_f); | |||
| tmp = expf(-2.0f * PI * freq / samplerate_f); | |||
| else | |||
| tmp = 0.0f; | |||
| c[0] = (1.0f + tmp) / 2.0f; | |||
| @@ -276,7 +281,7 @@ void AnalogFilter::setfreq(float frequency) | |||
| rap = 1.0f / rap; | |||
| oldabovenq = abovenq; | |||
| abovenq = frequency > (synth->halfsamplerate_f - 500.0f); | |||
| abovenq = frequency > (halfsamplerate_f - 500.0f); | |||
| bool nyquistthresh = (abovenq ^ oldabovenq); | |||
| @@ -331,7 +336,7 @@ void AnalogFilter::singlefilterout(float *smp, fstage &hist, | |||
| const Coeff &coeff) | |||
| { | |||
| if(order == 1) //First order filter | |||
| for(int i = 0; i < synth->buffersize; ++i) { | |||
| for(int i = 0; i < buffersize; ++i) { | |||
| float y0 = smp[i] * coeff.c[0] + hist.x1 * coeff.c[1] | |||
| + hist.y1 * coeff.d[1]; | |||
| hist.y1 = y0; | |||
| @@ -339,7 +344,7 @@ void AnalogFilter::singlefilterout(float *smp, fstage &hist, | |||
| smp[i] = y0; | |||
| } | |||
| if(order == 2) //Second order filter | |||
| for(int i = 0; i < synth->buffersize; ++i) { | |||
| for(int i = 0; i < buffersize; ++i) { | |||
| float y0 = smp[i] * coeff.c[0] + hist.x1 * coeff.c[1] | |||
| + hist.x2 * coeff.c[2] + hist.y1 * coeff.d[1] | |||
| + hist.y2 * coeff.d[2]; | |||
| @@ -359,26 +364,26 @@ void AnalogFilter::filterout(float *smp) | |||
| if(needsinterpolation) { | |||
| //Merge Filter at old coeff with new coeff | |||
| float *ismp = getTmpBuffer(); | |||
| memcpy(ismp, smp, synth->bufferbytes); | |||
| memcpy(ismp, smp, buffersize*sizeof(float)); | |||
| for(int i = 0; i < stages + 1; ++i) | |||
| singlefilterout(ismp, oldHistory[i], oldCoeff); | |||
| for(int i = 0; i < synth->buffersize; ++i) { | |||
| float x = (float)i / synth->buffersize_f; | |||
| for(int i = 0; i < buffersize; ++i) { | |||
| float x = (float)i / buffersize_f; | |||
| smp[i] = ismp[i] * (1.0f - x) + smp[i] * x; | |||
| } | |||
| returnTmpBuffer(ismp); | |||
| needsinterpolation = false; | |||
| } | |||
| for(int i = 0; i < synth->buffersize; ++i) | |||
| for(int i = 0; i < buffersize; ++i) | |||
| smp[i] *= outgain; | |||
| } | |||
| float AnalogFilter::H(float freq) | |||
| { | |||
| float fr = freq / synth->samplerate_f * PI * 2.0f; | |||
| float fr = freq / samplerate_f * PI * 2.0f; | |||
| float x = coeff.c[0], y = 0.0f; | |||
| for(int n = 1; n < 3; ++n) { | |||
| x += cosf(n * fr) * coeff.c[n]; | |||
| @@ -35,7 +35,7 @@ class AnalogFilter:public Filter | |||
| { | |||
| public: | |||
| AnalogFilter(unsigned char Ftype, float Ffreq, float Fq, | |||
| unsigned char Fstages); | |||
| unsigned char Fstages, float srate, int bufsize); | |||
| ~AnalogFilter(); | |||
| void filterout(float *smp); | |||
| void setfreq(float frequency); | |||
| @@ -79,6 +79,11 @@ class AnalogFilter:public Filter | |||
| bool abovenq, //if the frequency is above the nyquist | |||
| oldabovenq; //if the last time was above nyquist | |||
| //(used to see if it needs interpolation) | |||
| float samplerate_f; | |||
| float halfsamplerate_f; | |||
| int buffersize; | |||
| float buffersize_f; | |||
| }; | |||
| @@ -29,24 +29,29 @@ | |||
| #include "SVFilter.h" | |||
| #include "../Params/FilterParams.h" | |||
| Filter *Filter::generate(FilterParams *pars) | |||
| Filter *Filter::generate(FilterParams *pars, float srate, int bufsize) | |||
| { | |||
| if (srate == 0.0f) | |||
| srate = synth->samplerate_f; | |||
| if (bufsize == 0) | |||
| bufsize = synth->buffersize; | |||
| unsigned char Ftype = pars->Ptype; | |||
| unsigned char Fstages = pars->Pstages; | |||
| Filter *filter; | |||
| switch(pars->Pcategory) { | |||
| case 1: | |||
| filter = new FormantFilter(pars); | |||
| filter = new FormantFilter(pars, srate, bufsize); | |||
| break; | |||
| case 2: | |||
| filter = new SVFilter(Ftype, 1000.0f, pars->getq(), Fstages); | |||
| filter = new SVFilter(Ftype, 1000.0f, pars->getq(), Fstages, srate, bufsize); | |||
| filter->outgain = dB2rap(pars->getgain()); | |||
| if(filter->outgain > 1.0f) | |||
| filter->outgain = sqrt(filter->outgain); | |||
| break; | |||
| default: | |||
| filter = new AnalogFilter(Ftype, 1000.0f, pars->getq(), Fstages); | |||
| filter = new AnalogFilter(Ftype, 1000.0f, pars->getq(), Fstages, srate, bufsize); | |||
| if((Ftype >= 6) && (Ftype <= 8)) | |||
| filter->setgain(pars->getgain()); | |||
| else | |||
| @@ -29,7 +29,7 @@ class Filter | |||
| { | |||
| public: | |||
| static float getrealfreq(float freqpitch); | |||
| static Filter *generate(class FilterParams * pars); | |||
| static Filter *generate(class FilterParams * pars, float srate = 0, int bufsize = 0); | |||
| virtual ~Filter() {} | |||
| virtual void filterout(float *smp) = 0; | |||
| @@ -27,11 +27,12 @@ | |||
| #include "AnalogFilter.h" | |||
| #include "../Params/FilterParams.h" | |||
| FormantFilter::FormantFilter(FilterParams *pars) | |||
| FormantFilter::FormantFilter(FilterParams *pars, float srate, int bufsize) | |||
| { | |||
| buffersize = bufsize; | |||
| numformants = pars->Pnumformants; | |||
| for(int i = 0; i < numformants; ++i) | |||
| formant[i] = new AnalogFilter(4 /*BPF*/, 1000.0f, 10.0f, pars->Pstages); | |||
| formant[i] = new AnalogFilter(4 /*BPF*/, 1000.0f, 10.0f, pars->Pstages, srate, bufsize); | |||
| cleanup(); | |||
| for(int j = 0; j < FF_MAX_VOWELS; ++j) | |||
| @@ -205,24 +206,24 @@ void FormantFilter::filterout(float *smp) | |||
| { | |||
| float *inbuffer = getTmpBuffer(); | |||
| memcpy(inbuffer, smp, synth->bufferbytes); | |||
| memset(smp, 0, synth->bufferbytes); | |||
| memcpy(inbuffer, smp, buffersize*sizeof(float)); | |||
| memset(smp, 0, buffersize*sizeof(float)); | |||
| for(int j = 0; j < numformants; ++j) { | |||
| float *tmpbuf = getTmpBuffer(); | |||
| for(int i = 0; i < synth->buffersize; ++i) | |||
| for(int i = 0; i < buffersize; ++i) | |||
| tmpbuf[i] = inbuffer[i] * outgain; | |||
| formant[j]->filterout(tmpbuf); | |||
| if(ABOVE_AMPLITUDE_THRESHOLD(oldformantamp[j], currentformants[j].amp)) | |||
| for(int i = 0; i < synth->buffersize; ++i) | |||
| for(int i = 0; i < buffersize; ++i) | |||
| smp[i] += tmpbuf[i] | |||
| * INTERPOLATE_AMPLITUDE(oldformantamp[j], | |||
| currentformants[j].amp, | |||
| i, | |||
| synth->buffersize); | |||
| buffersize); | |||
| else | |||
| for(int i = 0; i < synth->buffersize; ++i) | |||
| for(int i = 0; i < buffersize; ++i) | |||
| smp[i] += tmpbuf[i] * currentformants[j].amp; | |||
| returnTmpBuffer(tmpbuf); | |||
| oldformantamp[j] = currentformants[j].amp; | |||
| @@ -30,7 +30,7 @@ | |||
| class FormantFilter:public Filter | |||
| { | |||
| public: | |||
| FormantFilter(class FilterParams *pars); | |||
| FormantFilter(class FilterParams *pars, float srate, int bufsize); | |||
| ~FormantFilter(); | |||
| void filterout(float *smp); | |||
| void setfreq(float frequency); | |||
| @@ -61,6 +61,8 @@ class FormantFilter:public Filter | |||
| float oldinput, slowinput; | |||
| float Qfactor, formantslowness, oldQfactor; | |||
| float vowelclearness, sequencestretch; | |||
| int buffersize; | |||
| }; | |||
| #endif | |||
| @@ -29,14 +29,16 @@ | |||
| #include "SVFilter.h" | |||
| SVFilter::SVFilter(unsigned char Ftype, float Ffreq, float Fq, | |||
| unsigned char Fstages) | |||
| unsigned char Fstages, float srate, int bufsize) | |||
| :type(Ftype), | |||
| stages(Fstages), | |||
| freq(Ffreq), | |||
| q(Fq), | |||
| gain(1.0f), | |||
| needsinterpolation(false), | |||
| firsttime(true) | |||
| firsttime(true), | |||
| samplerate_f(srate), | |||
| buffersize(bufsize) | |||
| { | |||
| if(stages >= MAX_FILTER_STAGES) | |||
| stages = MAX_FILTER_STAGES; | |||
| @@ -58,7 +60,7 @@ void SVFilter::cleanup() | |||
| void SVFilter::computefiltercoefs(void) | |||
| { | |||
| par.f = freq / synth->samplerate_f * 4.0f; | |||
| par.f = freq / samplerate_f * 4.0f; | |||
| if(par.f > 0.99999f) | |||
| par.f = 0.99999f; | |||
| par.q = 1.0f - atanf(sqrtf(q)) * 2.0f / PI; | |||
| @@ -76,7 +78,7 @@ void SVFilter::setfreq(float frequency) | |||
| rap = 1.0f / rap; | |||
| oldabovenq = abovenq; | |||
| abovenq = frequency > (synth->samplerate_f / 2 - 500.0f); | |||
| abovenq = frequency > (samplerate_f / 2 - 500.0f); | |||
| bool nyquistthresh = (abovenq ^ oldabovenq); | |||
| @@ -144,7 +146,7 @@ void SVFilter::singlefilterout(float *smp, fstage &x, parameters &par) | |||
| errx(1, "Impossible SVFilter type encountered [%d]", type); | |||
| } | |||
| for(int i = 0; i < synth->buffersize; ++i) { | |||
| for(int i = 0; i < buffersize; ++i) { | |||
| x.low = x.low + par.f * x.band; | |||
| x.high = par.q_sqrt * smp[i] - x.low - par.q * x.band; | |||
| x.band = par.f * x.high + x.band; | |||
| @@ -160,19 +162,19 @@ void SVFilter::filterout(float *smp) | |||
| if(needsinterpolation) { | |||
| float *ismp = getTmpBuffer(); | |||
| memcpy(ismp, smp, synth->bufferbytes); | |||
| memcpy(ismp, smp, buffersize*sizeof(float)); | |||
| for(int i = 0; i < stages + 1; ++i) | |||
| singlefilterout(ismp, st[i], ipar); | |||
| for(int i = 0; i < synth->buffersize; ++i) { | |||
| float x = i / synth->buffersize_f; | |||
| for(int i = 0; i < buffersize; ++i) { | |||
| float x = i / (float)buffersize; | |||
| smp[i] = ismp[i] * (1.0f - x) + smp[i] * x; | |||
| } | |||
| returnTmpBuffer(ismp); | |||
| needsinterpolation = false; | |||
| } | |||
| for(int i = 0; i < synth->buffersize; ++i) | |||
| for(int i = 0; i < buffersize; ++i) | |||
| smp[i] *= outgain; | |||
| } | |||
| @@ -32,7 +32,7 @@ class SVFilter:public Filter | |||
| SVFilter(unsigned char Ftype, | |||
| float Ffreq, | |||
| float Fq, | |||
| unsigned char Fstages); | |||
| unsigned char Fstages, float srate, int bufsize); | |||
| ~SVFilter(); | |||
| void filterout(float *smp); | |||
| void setfreq(float frequency); | |||
| @@ -64,6 +64,9 @@ class SVFilter:public Filter | |||
| bool abovenq, //if the frequency is above the nyquist | |||
| oldabovenq; | |||
| bool needsinterpolation, firsttime; | |||
| float samplerate_f; | |||
| int buffersize; | |||
| }; | |||
| #endif | |||
| @@ -23,8 +23,9 @@ | |||
| #include <cmath> | |||
| #include "Alienwah.h" | |||
| Alienwah::Alienwah(bool insertion_, float *efxoutl_, float *efxoutr_) | |||
| :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0), | |||
| Alienwah::Alienwah(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize) | |||
| :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0, srate, bufsize), | |||
| lfo(srate, bufsize), | |||
| oldl(NULL), | |||
| oldr(NULL) | |||
| { | |||
| @@ -58,8 +59,8 @@ void Alienwah::out(const Stereo<float *> &smp) | |||
| clfol = complex<float>(cosf(lfol + phase) * fb, sinf(lfol + 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; | |||
| //left | |||
| complex<float> tmp = clfol * x + oldclfol * x1; | |||
| @@ -44,7 +44,8 @@ class Alienwah:public Effect | |||
| */ | |||
| Alienwah(bool insertion_, | |||
| float *const efxoutl_, | |||
| float *const efxoutr_); | |||
| float *const efxoutr_, | |||
| unsigned int srate, int bufsize); | |||
| ~Alienwah(); | |||
| void out(const Stereo<float *> &smp); | |||
| @@ -26,9 +26,10 @@ | |||
| using namespace std; | |||
| Chorus::Chorus(bool insertion_, float *const efxoutl_, float *efxoutr_) | |||
| :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0), | |||
| maxdelay((int)(MAX_CHORUS_DELAY / 1000.0f * synth->samplerate_f)), | |||
| Chorus::Chorus(bool insertion_, float *const efxoutl_, float *efxoutr_, unsigned int srate, int bufsize) | |||
| :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0, srate, bufsize), | |||
| lfo(srate, bufsize), | |||
| maxdelay((int)(MAX_CHORUS_DELAY / 1000.0f * (float)srate)), | |||
| delaySample(new float[maxdelay], new float[maxdelay]) | |||
| { | |||
| dlk = 0; | |||
| @@ -51,7 +52,7 @@ Chorus::~Chorus() | |||
| float Chorus::getdelay(float xlfo) | |||
| { | |||
| float result = | |||
| (Pflangemode) ? 0 : (delay + xlfo * depth) * synth->samplerate_f; | |||
| (Pflangemode) ? 0 : (delay + xlfo * depth) * (float)samplerate; | |||
| //check if delay is too big (caused by bad setdelay() and setdepth() | |||
| if((result + 0.5f) >= maxdelay) { | |||
| @@ -75,7 +76,7 @@ void Chorus::out(const Stereo<float *> &input) | |||
| dl2 = getdelay(lfol); | |||
| dr2 = getdelay(lfor); | |||
| for(int i = 0; i < synth->buffersize; ++i) { | |||
| for(int i = 0; i < buffersize; ++i) { | |||
| float inL = input.l[i]; | |||
| float inR = input.r[i]; | |||
| //LRcross | |||
| @@ -87,7 +88,7 @@ void Chorus::out(const Stereo<float *> &input) | |||
| //compute the delay in samples using linear interpolation between the lfo delays | |||
| float mdel = | |||
| (dl1 * (synth->buffersize - i) + dl2 * i) / synth->buffersize_f; | |||
| (dl1 * (buffersize - i) + dl2 * i) / (float)buffersize; | |||
| if(++dlk >= maxdelay) | |||
| dlk = 0; | |||
| float tmp = dlk - mdel + maxdelay * 2.0f; //where should I get the sample from | |||
| @@ -105,7 +106,7 @@ void Chorus::out(const Stereo<float *> &input) | |||
| //Right channel | |||
| //compute the delay in samples using linear interpolation between the lfo delays | |||
| mdel = (dr1 * (synth->buffersize - i) + dr2 * i) / synth->buffersize_f; | |||
| mdel = (dr1 * (buffersize - i) + dr2 * i) / (float)buffersize; | |||
| if(++drk >= maxdelay) | |||
| drk = 0; | |||
| tmp = drk * 1.0f - mdel + maxdelay * 2.0f; //where should I get the sample from | |||
| @@ -122,12 +123,12 @@ void Chorus::out(const Stereo<float *> &input) | |||
| } | |||
| if(Poutsub) | |||
| for(int i = 0; i < synth->buffersize; ++i) { | |||
| for(int i = 0; i < buffersize; ++i) { | |||
| efxoutl[i] *= -1.0f; | |||
| efxoutr[i] *= -1.0f; | |||
| } | |||
| for(int i = 0; i < synth->buffersize; ++i) { | |||
| for(int i = 0; i < buffersize; ++i) { | |||
| efxoutl[i] *= pangainL; | |||
| efxoutr[i] *= pangainR; | |||
| } | |||
| @@ -32,7 +32,7 @@ | |||
| class Chorus:public Effect | |||
| { | |||
| public: | |||
| Chorus(bool insertion_, float *efxoutl_, float *efxoutr_); | |||
| Chorus(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize); | |||
| /**Destructor*/ | |||
| ~Chorus(); | |||
| void out(const Stereo<float *> &input); | |||
| @@ -25,8 +25,8 @@ | |||
| #include "../Misc/WaveShapeSmps.h" | |||
| #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), | |||
| Pdrive(90), | |||
| Plevel(64), | |||
| @@ -37,10 +37,10 @@ Distorsion::Distorsion(bool insertion_, float *efxoutl_, float *efxoutr_) | |||
| Pstereo(0), | |||
| Pprefiltering(0) | |||
| { | |||
| lpfl = new AnalogFilter(2, 22000, 1, 0); | |||
| lpfr = new AnalogFilter(2, 22000, 1, 0); | |||
| hpfl = new AnalogFilter(3, 20, 1, 0); | |||
| hpfr = new AnalogFilter(3, 20, 1, 0); | |||
| lpfl = new AnalogFilter(2, 22000, 1, 0, srate, bufsize); | |||
| lpfr = new AnalogFilter(2, 22000, 1, 0, srate, bufsize); | |||
| hpfl = new AnalogFilter(3, 20, 1, 0, srate, bufsize); | |||
| hpfr = new AnalogFilter(3, 20, 1, 0, srate, bufsize); | |||
| setpreset(Ppreset); | |||
| cleanup(); | |||
| } | |||
| @@ -83,29 +83,29 @@ void Distorsion::out(const Stereo<float *> &smp) | |||
| inputvol *= -1.0f; | |||
| if(Pstereo) //Stereo | |||
| for(int i = 0; i < synth->buffersize; ++i) { | |||
| for(int i = 0; i < buffersize; ++i) { | |||
| efxoutl[i] = smp.l[i] * inputvol * pangainL; | |||
| efxoutr[i] = smp.r[i] * inputvol * pangainR; | |||
| } | |||
| else //Mono | |||
| for(int i = 0; i < synth->buffersize; ++i) | |||
| for(int i = 0; i < buffersize; ++i) | |||
| efxoutl[i] = (smp.l[i] * pangainL + smp.r[i] * pangainR) * inputvol; | |||
| if(Pprefiltering) | |||
| applyfilters(efxoutl, efxoutr); | |||
| waveShapeSmps(synth->buffersize, efxoutl, Ptype + 1, Pdrive); | |||
| waveShapeSmps(buffersize, efxoutl, Ptype + 1, Pdrive); | |||
| if(Pstereo) | |||
| waveShapeSmps(synth->buffersize, efxoutr, Ptype + 1, Pdrive); | |||
| waveShapeSmps(buffersize, efxoutr, Ptype + 1, Pdrive); | |||
| if(!Pprefiltering) | |||
| applyfilters(efxoutl, efxoutr); | |||
| if(!Pstereo) | |||
| memcpy(efxoutr, efxoutl, synth->bufferbytes); | |||
| memcpy(efxoutr, efxoutl, buffersize*sizeof(float)); | |||
| float level = dB2rap(60.0f * Plevel / 127.0f - 40.0f); | |||
| for(int i = 0; i < synth->buffersize; ++i) { | |||
| for(int i = 0; i < buffersize; ++i) { | |||
| float lout = efxoutl[i]; | |||
| float rout = efxoutr[i]; | |||
| float l = lout * (1.0f - lrcross) + rout * lrcross; | |||
| @@ -29,7 +29,7 @@ | |||
| class Distorsion:public Effect | |||
| { | |||
| public: | |||
| Distorsion(bool insertion, float *efxoutl_, float *efxoutr_); | |||
| Distorsion(bool insertion, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize); | |||
| ~Distorsion(); | |||
| void out(const Stereo<float *> &smp); | |||
| void setpreset(unsigned char npreset); | |||
| @@ -24,8 +24,9 @@ | |||
| #include "DynamicFilter.h" | |||
| #include "../DSP/Filter.h" | |||
| DynamicFilter::DynamicFilter(bool insertion_, float *efxoutl_, float *efxoutr_) | |||
| :Effect(insertion_, efxoutl_, efxoutr_, new FilterParams(0, 64, 64), 0), | |||
| DynamicFilter::DynamicFilter(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize) | |||
| :Effect(insertion_, efxoutl_, efxoutr_, new FilterParams(0, 64, 64), 0, srate, bufsize), | |||
| lfo(srate, bufsize), | |||
| Pvolume(110), | |||
| Pdepth(0), | |||
| Pampsns(90), | |||
| @@ -61,7 +62,7 @@ void DynamicFilter::out(const Stereo<float *> &smp) | |||
| const float freq = filterpars->getfreq(); | |||
| const float q = filterpars->getq(); | |||
| for(int i = 0; i < synth->buffersize; ++i) { | |||
| for(int i = 0; i < buffersize; ++i) { | |||
| efxoutl[i] = smp.l[i]; | |||
| efxoutr[i] = smp.r[i]; | |||
| @@ -85,7 +86,7 @@ void DynamicFilter::out(const Stereo<float *> &smp) | |||
| filterr->filterout(efxoutr); | |||
| //panning | |||
| for(int i = 0; i < synth->buffersize; ++i) { | |||
| for(int i = 0; i < buffersize; ++i) { | |||
| efxoutl[i] *= pangainL; | |||
| efxoutr[i] *= pangainR; | |||
| } | |||
| @@ -130,8 +131,8 @@ void DynamicFilter::reinitfilter(void) | |||
| { | |||
| delete filterl; | |||
| delete filterr; | |||
| filterl = Filter::generate(filterpars); | |||
| filterr = Filter::generate(filterpars); | |||
| filterl = Filter::generate(filterpars, samplerate, buffersize); | |||
| filterr = Filter::generate(filterpars, samplerate, buffersize); | |||
| } | |||
| void DynamicFilter::setpreset(unsigned char npreset) | |||
| @@ -30,7 +30,7 @@ | |||
| class DynamicFilter:public Effect | |||
| { | |||
| public: | |||
| DynamicFilter(bool insertion_, float *efxoutl_, float *efxoutr_); | |||
| DynamicFilter(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize); | |||
| ~DynamicFilter(); | |||
| void out(const Stereo<float *> &smp); | |||
| @@ -24,8 +24,8 @@ | |||
| #include "EQ.h" | |||
| #include "../DSP/AnalogFilter.h" | |||
| EQ::EQ(bool insertion_, float *efxoutl_, float *efxoutr_) | |||
| :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0) | |||
| EQ::EQ(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize) | |||
| :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0, srate, bufsize) | |||
| { | |||
| for(int i = 0; i < MAX_EQ_BANDS; ++i) { | |||
| filter[i].Ptype = 0; | |||
| @@ -33,8 +33,8 @@ EQ::EQ(bool insertion_, float *efxoutl_, float *efxoutr_) | |||
| filter[i].Pgain = 64; | |||
| filter[i].Pq = 64; | |||
| filter[i].Pstages = 0; | |||
| filter[i].l = new AnalogFilter(6, 1000.0f, 1.0f, 0); | |||
| filter[i].r = new AnalogFilter(6, 1000.0f, 1.0f, 0); | |||
| filter[i].l = new AnalogFilter(6, 1000.0f, 1.0f, 0, srate, bufsize); | |||
| filter[i].r = new AnalogFilter(6, 1000.0f, 1.0f, 0, srate, bufsize); | |||
| } | |||
| //default values | |||
| Pvolume = 50; | |||
| @@ -56,7 +56,7 @@ void EQ::cleanup(void) | |||
| //Effect output | |||
| void EQ::out(const Stereo<float *> &smp) | |||
| { | |||
| for(int i = 0; i < synth->buffersize; ++i) { | |||
| for(int i = 0; i < buffersize; ++i) { | |||
| efxoutl[i] = smp.l[i] * volume; | |||
| efxoutr[i] = smp.r[i] * volume; | |||
| } | |||
| @@ -29,7 +29,7 @@ | |||
| class EQ:public Effect | |||
| { | |||
| public: | |||
| EQ(bool insertion_, float *efxoutl_, float *efxoutr_); | |||
| EQ(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize); | |||
| ~EQ() {} | |||
| void out(const Stereo<float *> &smp); | |||
| void setpreset(unsigned char npreset); | |||
| @@ -27,8 +27,8 @@ | |||
| #define MAX_DELAY 2 | |||
| Echo::Echo(bool insertion_, float *efxoutl_, float *efxoutr_) | |||
| :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0), | |||
| Echo::Echo(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize) | |||
| :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0, srate, bufsize), | |||
| Pvolume(50), | |||
| Pdelay(60), | |||
| Plrdelay(100), | |||
| @@ -37,8 +37,8 @@ Echo::Echo(bool insertion_, float *efxoutl_, float *efxoutr_) | |||
| delayTime(1), | |||
| lrdelay(0), | |||
| avgDelay(0), | |||
| delay(new float[(int)(MAX_DELAY * synth->samplerate)], | |||
| new float[(int)(MAX_DELAY * synth->samplerate)]), | |||
| delay(new float[(int)(MAX_DELAY * srate)], | |||
| new float[(int)(MAX_DELAY * srate)]), | |||
| old(0.0f), | |||
| pos(0), | |||
| delta(1), | |||
| @@ -57,8 +57,8 @@ Echo::~Echo() | |||
| //Cleanup the effect | |||
| void Echo::cleanup(void) | |||
| { | |||
| memset(delay.l, 0, MAX_DELAY * synth->samplerate * sizeof(float)); | |||
| memset(delay.r, 0, MAX_DELAY * synth->samplerate * sizeof(float)); | |||
| memset(delay.l, 0, MAX_DELAY * samplerate * sizeof(float)); | |||
| memset(delay.r, 0, MAX_DELAY * samplerate * sizeof(float)); | |||
| old = Stereo<float>(0.0f); | |||
| } | |||
| @@ -77,14 +77,14 @@ void Echo::initdelays(void) | |||
| //number of seconds to delay right chan | |||
| float dr = avgDelay + lrdelay; | |||
| ndelta.l = max(1, (int) (dl * synth->samplerate)); | |||
| ndelta.r = max(1, (int) (dr * synth->samplerate)); | |||
| ndelta.l = max(1, (int) (dl * samplerate)); | |||
| ndelta.r = max(1, (int) (dr * samplerate)); | |||
| } | |||
| //Effect output | |||
| void Echo::out(const Stereo<float *> &input) | |||
| { | |||
| for(int i = 0; i < synth->buffersize; ++i) { | |||
| for(int i = 0; i < buffersize; ++i) { | |||
| float ldl = delay.l[pos.l]; | |||
| float rdl = delay.r[pos.r]; | |||
| ldl = ldl * (1.0f - lrcross) + rdl * lrcross; | |||
| @@ -97,9 +97,9 @@ void Echo::out(const Stereo<float *> &input) | |||
| rdl = input.r[i] * pangainR - rdl * fb; | |||
| //LowPass Filter | |||
| old.l = delay.l[(pos.l + delta.l) % (MAX_DELAY * synth->samplerate)] = | |||
| old.l = delay.l[(pos.l + delta.l) % (MAX_DELAY * samplerate)] = | |||
| ldl * hidamp + old.l * (1.0f - hidamp); | |||
| old.r = delay.r[(pos.r + delta.r) % (MAX_DELAY * synth->samplerate)] = | |||
| old.r = delay.r[(pos.r + delta.r) % (MAX_DELAY * samplerate)] = | |||
| rdl * hidamp + old.r * (1.0f - hidamp); | |||
| //increment | |||
| @@ -107,8 +107,8 @@ void Echo::out(const Stereo<float *> &input) | |||
| ++pos.r; // += delta.r; | |||
| //ensure that pos is still in bounds | |||
| pos.l %= MAX_DELAY * synth->samplerate; | |||
| pos.r %= MAX_DELAY * synth->samplerate; | |||
| pos.l %= MAX_DELAY * samplerate; | |||
| pos.r %= MAX_DELAY * samplerate; | |||
| //adjust delay if needed | |||
| delta.l = (15 * delta.l + ndelta.l) / 16; | |||
| @@ -30,7 +30,7 @@ | |||
| class Echo:public Effect | |||
| { | |||
| public: | |||
| Echo(bool insertion_, float *efxoutl_, float *efxoutr_); | |||
| Echo(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize); | |||
| ~Echo(); | |||
| void out(const Stereo<float *> &input); | |||
| @@ -26,12 +26,15 @@ | |||
| #include <cmath> | |||
| Effect::Effect(bool insertion_, float *efxoutl_, float *efxoutr_, | |||
| FilterParams *filterpars_, unsigned char Ppreset_) | |||
| FilterParams *filterpars_, unsigned char Ppreset_, | |||
| unsigned int srate, int bufsize) | |||
| :Ppreset(Ppreset_), | |||
| efxoutl(efxoutl_), | |||
| efxoutr(efxoutr_), | |||
| filterpars(filterpars_), | |||
| insertion(insertion_) | |||
| insertion(insertion_), | |||
| samplerate(srate), | |||
| buffersize(bufsize) | |||
| {} | |||
| void Effect::out(float *const smpsl, float *const smpsr) | |||
| @@ -24,7 +24,6 @@ | |||
| #define EFFECT_H | |||
| #include "../Misc/Util.h" | |||
| #include "../globals.h" | |||
| #include "../Params/FilterParams.h" | |||
| #include "../Misc/Stereo.h" | |||
| @@ -43,7 +42,8 @@ class Effect | |||
| * @param Ppreset_ chosen preset | |||
| * @return Initialized Effect object*/ | |||
| Effect(bool insertion_, float *efxoutl_, float *efxoutr_, | |||
| FilterParams *filterpars_, unsigned char Ppreset_); | |||
| FilterParams *filterpars_, unsigned char Ppreset_, | |||
| unsigned int srate, int bufsize); | |||
| virtual ~Effect() {} | |||
| /** | |||
| * Choose a preset | |||
| @@ -100,6 +100,10 @@ class Effect | |||
| float pangainR; | |||
| char Plrcross; // L/R mix | |||
| float lrcross; | |||
| // current setup | |||
| unsigned int samplerate; | |||
| int buffersize; | |||
| }; | |||
| #endif | |||
| @@ -25,7 +25,7 @@ | |||
| #include <cmath> | |||
| EffectLFO::EffectLFO(void) | |||
| EffectLFO::EffectLFO(float srate, float bufsize) | |||
| :Pfreq(40), | |||
| Prandomness(0), | |||
| PLFOtype(0), | |||
| @@ -36,7 +36,9 @@ EffectLFO::EffectLFO(void) | |||
| ampl2(RND), | |||
| ampr1(RND), | |||
| ampr2(RND), | |||
| lfornd(0.0f) | |||
| lfornd(0.0f), | |||
| samplerate_f(srate), | |||
| buffersize_f(bufsize) | |||
| { | |||
| updateparams(); | |||
| } | |||
| @@ -47,7 +49,7 @@ EffectLFO::~EffectLFO() {} | |||
| void EffectLFO::updateparams(void) | |||
| { | |||
| float lfofreq = (powf(2.0f, Pfreq / 127.0f * 10.0f) - 1.0f) * 0.03f; | |||
| incx = fabsf(lfofreq) * synth->buffersize_f / synth->samplerate_f; | |||
| incx = fabsf(lfofreq) * buffersize_f / samplerate_f; | |||
| if(incx > 0.49999999f) | |||
| incx = 0.499999999f; //Limit the Frequency | |||
| @@ -28,7 +28,7 @@ | |||
| class EffectLFO | |||
| { | |||
| public: | |||
| EffectLFO(); | |||
| EffectLFO(float srate, float bufsize); | |||
| ~EffectLFO(); | |||
| void effectlfoout(float *outl, float *outr); | |||
| void updateparams(void); | |||
| @@ -45,6 +45,9 @@ class EffectLFO | |||
| float lfointensity; | |||
| float lfornd; | |||
| char lfotype; | |||
| float samplerate_f; | |||
| float buffersize_f; | |||
| }; | |||
| #endif | |||
| @@ -76,28 +76,28 @@ void EffectMgr::changeeffect(int _nefx) | |||
| delete efx; | |||
| switch(nefx) { | |||
| case 1: | |||
| efx = new Reverb(insertion, efxoutl, efxoutr); | |||
| efx = new Reverb(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize); | |||
| break; | |||
| case 2: | |||
| efx = new Echo(insertion, efxoutl, efxoutr); | |||
| efx = new Echo(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize); | |||
| break; | |||
| case 3: | |||
| efx = new Chorus(insertion, efxoutl, efxoutr); | |||
| efx = new Chorus(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize); | |||
| break; | |||
| case 4: | |||
| efx = new Phaser(insertion, efxoutl, efxoutr); | |||
| efx = new Phaser(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize); | |||
| break; | |||
| case 5: | |||
| efx = new Alienwah(insertion, efxoutl, efxoutr); | |||
| efx = new Alienwah(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize); | |||
| break; | |||
| case 6: | |||
| efx = new Distorsion(insertion, efxoutl, efxoutr); | |||
| efx = new Distorsion(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize); | |||
| break; | |||
| case 7: | |||
| efx = new EQ(insertion, efxoutl, efxoutr); | |||
| efx = new EQ(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize); | |||
| break; | |||
| case 8: | |||
| efx = new DynamicFilter(insertion, efxoutl, efxoutr); | |||
| efx = new DynamicFilter(insertion, efxoutl, efxoutr, synth->samplerate, synth->buffersize); | |||
| break; | |||
| //put more effect here | |||
| default: | |||
| @@ -39,8 +39,8 @@ using namespace std; | |||
| #define ONE_ 0.99999f // To prevent LFO ever reaching 1.0f for filter stability purposes | |||
| #define ZERO_ 0.00001f // Same idea as above. | |||
| Phaser::Phaser(const int &insertion_, float *efxoutl_, float *efxoutr_) | |||
| :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0), old(NULL), xn1(NULL), | |||
| Phaser::Phaser(const int &insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize) | |||
| :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0, srate, bufsize), lfo(srate, bufsize), old(NULL), xn1(NULL), | |||
| yn1(NULL), diff(0.0f), oldgain(0.0f), fb(0.0f) | |||
| { | |||
| analog_setup(); | |||
| @@ -72,8 +72,8 @@ void Phaser::analog_setup() | |||
| Rmx = Rmin / Rmax; | |||
| Rconst = 1.0f + Rmx; // Handle parallel resistor relationship | |||
| C = 0.00000005f; // 50 nF | |||
| CFs = 2.0f * synth->samplerate_f * C; | |||
| invperiod = 1.0f / synth->buffersize_f; | |||
| CFs = 2.0f * float(samplerate) * C; | |||
| invperiod = 1.0f / float(buffersize); | |||
| } | |||
| Phaser::~Phaser() | |||
| @@ -129,7 +129,7 @@ void Phaser::AnalogPhase(const Stereo<float *> &input) | |||
| g = oldgain; | |||
| oldgain = mod; | |||
| for(int i = 0; i < synth->buffersize; ++i) { | |||
| for(int i = 0; i < buffersize; ++i) { | |||
| g.l += diff.l; // Linear interpolation between LFO samples | |||
| g.r += diff.r; | |||
| @@ -151,8 +151,8 @@ void Phaser::AnalogPhase(const Stereo<float *> &input) | |||
| } | |||
| if(Poutsub) { | |||
| invSignal(efxoutl, synth->buffersize); | |||
| invSignal(efxoutr, synth->buffersize); | |||
| invSignal(efxoutl, buffersize); | |||
| invSignal(efxoutr, buffersize); | |||
| } | |||
| } | |||
| @@ -202,8 +202,8 @@ void Phaser::normalPhase(const Stereo<float *> &input) | |||
| gain.l = limit(gain.l, ZERO_, ONE_); | |||
| gain.r = limit(gain.r, ZERO_, ONE_); | |||
| for(int i = 0; i < synth->buffersize; ++i) { | |||
| float x = (float) i / synth->buffersize_f; | |||
| for(int i = 0; i < buffersize; ++i) { | |||
| float x = float(i) / float(buffersize); | |||
| float x1 = 1.0f - x; | |||
| //TODO think about making panning an external feature | |||
| Stereo<float> xn(input.l[i] * pangainL + fb.l, | |||
| @@ -227,8 +227,8 @@ void Phaser::normalPhase(const Stereo<float *> &input) | |||
| oldgain = gain; | |||
| if(Poutsub) { | |||
| invSignal(efxoutl, synth->buffersize); | |||
| invSignal(efxoutr, synth->buffersize); | |||
| invSignal(efxoutl, buffersize); | |||
| invSignal(efxoutr, buffersize); | |||
| } | |||
| } | |||
| @@ -35,7 +35,7 @@ | |||
| class Phaser:public Effect | |||
| { | |||
| public: | |||
| Phaser(const int &insertion_, float *efxoutl_, float *efxoutr_); | |||
| Phaser(const int &insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize); | |||
| ~Phaser(); | |||
| void out(const Stereo<float *> &input); | |||
| void setpreset(unsigned char npreset); | |||
| @@ -28,8 +28,8 @@ | |||
| //todo: EarlyReflections, Prdelay, Perbalance | |||
| Reverb::Reverb(bool insertion_, float *efxoutl_, float *efxoutr_) | |||
| :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0), | |||
| Reverb::Reverb(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize) | |||
| :Effect(insertion_, efxoutl_, efxoutr_, NULL, 0, srate, bufsize), | |||
| // defaults | |||
| Pvolume(48), | |||
| Ptime(64), | |||
| @@ -116,7 +116,7 @@ void Reverb::processmono(int ch, float *output, float *inputbuf) | |||
| const int comblength = comblen[j]; | |||
| float &lpcombj = lpcomb[j]; | |||
| for(int i = 0; i < synth->buffersize; ++i) { | |||
| for(int i = 0; i < buffersize; ++i) { | |||
| float fbout = comb[j][ck] * combfb[j]; | |||
| fbout = fbout * (1.0f - lohifb) + lpcombj * lohifb; | |||
| lpcombj = fbout; | |||
| @@ -132,7 +132,7 @@ void Reverb::processmono(int ch, float *output, float *inputbuf) | |||
| for(int j = REV_APS * ch; j < REV_APS * (1 + ch); ++j) { | |||
| int &ak = apk[j]; | |||
| const int aplength = aplen[j]; | |||
| for(int i = 0; i < synth->buffersize; ++i) { | |||
| for(int i = 0; i < buffersize; ++i) { | |||
| float tmp = ap[j][ak]; | |||
| ap[j][ak] = 0.7f * tmp + output[i]; | |||
| output[i] = tmp - 0.7f * ap[j][ak]; | |||
| @@ -149,11 +149,11 @@ void Reverb::out(const Stereo<float *> &smp) | |||
| return; | |||
| float *inputbuf = getTmpBuffer(); | |||
| for(int i = 0; i < synth->buffersize; ++i) | |||
| for(int i = 0; i < buffersize; ++i) | |||
| inputbuf[i] = (smp.l[i] + smp.r[i]) / 2.0f; | |||
| if(idelay) | |||
| for(int i = 0; i < synth->buffersize; ++i) { | |||
| for(int i = 0; i < buffersize; ++i) { | |||
| //Initial delay r | |||
| float tmp = inputbuf[i] + idelay[idelayk] * idelayfb; | |||
| inputbuf[i] = idelay[idelayk]; | |||
| @@ -164,7 +164,7 @@ void Reverb::out(const Stereo<float *> &smp) | |||
| } | |||
| if(bandwidth) | |||
| bandwidth->process(synth->buffersize, inputbuf); | |||
| bandwidth->process(buffersize, inputbuf); | |||
| if(lpf) | |||
| lpf->filterout(inputbuf); | |||
| @@ -181,7 +181,7 @@ void Reverb::out(const Stereo<float *> &smp) | |||
| lvol *= 2.0f; | |||
| rvol *= 2.0f; | |||
| } | |||
| for(int i = 0; i < synth->buffersize; ++i) { | |||
| for(int i = 0; i < buffersize; ++i) { | |||
| efxoutl[i] *= lvol; | |||
| efxoutr[i] *= rvol; | |||
| } | |||
| @@ -210,7 +210,7 @@ void Reverb::settime(unsigned char _Ptime) | |||
| for(int i = 0; i < REV_COMBS * 2; ++i) | |||
| combfb[i] = | |||
| -expf((float)comblen[i] / synth->samplerate_f * logf(0.001f) / t); | |||
| -expf((float)comblen[i] / (float)samplerate * logf(0.001f) / t); | |||
| //the feedback is negative because it removes the DC | |||
| } | |||
| @@ -241,7 +241,7 @@ void Reverb::setidelay(unsigned char _Pidelay) | |||
| delete [] idelay; | |||
| idelay = NULL; | |||
| idelaylen = (int) (synth->samplerate_f * delay / 1000); | |||
| idelaylen = (int) ((float)samplerate * delay / 1000.0f); | |||
| if(idelaylen > 1) { | |||
| idelayk = 0; | |||
| idelay = new float[idelaylen]; | |||
| @@ -266,7 +266,7 @@ void Reverb::sethpf(unsigned char _Phpf) | |||
| else { | |||
| float fr = expf(powf(Phpf / 127.0f, 0.5f) * logf(10000.0f)) + 20.0f; | |||
| if(hpf == NULL) | |||
| hpf = new AnalogFilter(3, fr, 1, 0); | |||
| hpf = new AnalogFilter(3, fr, 1, 0, samplerate, buffersize); | |||
| else | |||
| hpf->setfreq(fr); | |||
| } | |||
| @@ -283,7 +283,7 @@ void Reverb::setlpf(unsigned char _Plpf) | |||
| else { | |||
| float fr = expf(powf(Plpf / 127.0f, 0.5f) * logf(25000.0f)) + 40.0f; | |||
| if(!lpf) | |||
| lpf = new AnalogFilter(2, fr, 1, 0); | |||
| lpf = new AnalogFilter(2, fr, 1, 0, samplerate, buffersize); | |||
| else | |||
| lpf->setfreq(fr); | |||
| } | |||
| @@ -315,7 +315,7 @@ void Reverb::settype(unsigned char _Ptype) | |||
| Ptype = NUM_TYPES - 1; | |||
| // adjust the combs according to the samplerate | |||
| float samplerate_adjust = synth->samplerate_f / 44100.0f; | |||
| float samplerate_adjust = (float)samplerate / 44100.0f; | |||
| float tmp; | |||
| for(int i = 0; i < REV_COMBS * 2; ++i) { | |||
| if(Ptype == 0) | |||
| @@ -360,7 +360,7 @@ void Reverb::settype(unsigned char _Ptype) | |||
| //not been verified yet. | |||
| //As this cannot be resized in a RT context, a good upper bound should | |||
| //be found | |||
| bandwidth = new Unison(synth->buffersize / 4 + 1, 2.0f); | |||
| bandwidth = new Unison(buffersize / 4 + 1, 2.0f); | |||
| bandwidth->setSize(50); | |||
| bandwidth->setBaseFrequency(1.0f); | |||
| } | |||
| @@ -32,7 +32,7 @@ | |||
| class Reverb:public Effect | |||
| { | |||
| public: | |||
| Reverb(bool insertion_, float *efxoutl_, float *efxoutr_); | |||
| Reverb(bool insertion_, float *efxoutl_, float *efxoutr_, unsigned int srate, int bufsize); | |||
| ~Reverb(); | |||
| void out(const Stereo<float *> &smp); | |||
| void cleanup(void); | |||
| @@ -45,7 +45,7 @@ endif | |||
| # -------------------------------------------------------------- | |||
| # Native | |||
| DGL_LIBS = -lX11 | |||
| DGL_LIBS = -lX11 -lXext | |||
| ifeq ($(HAVE_OPENGL),true) | |||
| LINK_FLAGS += $(shell pkg-config --libs gl) $(DGL_LIBS) | |||
| @@ -76,6 +76,10 @@ LINK_FLAGS += $(EXTRA_LIBS) | |||
| LIBS = ../modules/carla_native.a | |||
| LIBS += ../modules/juce_audio_basics.a | |||
| LIBS += ../modules/juce_core.a | |||
| LIBS += ../modules/juce_data_structures.a | |||
| LIBS += ../modules/juce_events.a | |||
| LIBS += ../modules/juce_graphics.a | |||
| LIBS += ../modules/juce_gui_basics.a | |||
| LIBS += ../modules/rtmempool.a | |||
| # ifeq ($(CARLA_PLUGIN_SUPPORT),true) | |||
| @@ -143,7 +147,7 @@ carla-native-lv2-export.exe: carla-native-lv2-export.cpp.o $(LIBS) | |||
| # -------------------------------------------------------------- | |||
| .FORCE: | |||
| .PHONY: .FORCE | |||
| .PHONY: .FORCE carla-native-lv2-export carla-native-lv2-export.exe | |||
| ../modules/%.a: .FORCE | |||
| $(MAKE) -C ../modules $* | |||
| @@ -35,7 +35,8 @@ void carla_register_native_plugin_midiTranspose(); | |||
| void carla_register_native_plugin_nekofilter(); | |||
| // Simple plugins (C++) | |||
| void carla_register_native_plugin_vex(); | |||
| void carla_register_native_plugin_vex_fx(); | |||
| void carla_register_native_plugin_vex_synth(); | |||
| #ifdef WANT_AUDIOFILE | |||
| // AudioFile | |||
| @@ -63,7 +64,8 @@ void carla_register_native_plugin_Notes(); | |||
| #ifdef WANT_ZYNADDSUBFX | |||
| // ZynAddSubFX | |||
| void carla_register_native_plugin_zynaddsubfx(); | |||
| void carla_register_native_plugin_zynaddsubfx_fx(); | |||
| void carla_register_native_plugin_zynaddsubfx_synth(); | |||
| #endif | |||
| } | |||
| @@ -83,7 +85,8 @@ struct PluginListManager { | |||
| carla_register_native_plugin_nekofilter(); | |||
| // Simple plugins (C++) | |||
| carla_register_native_plugin_vex(); | |||
| carla_register_native_plugin_vex_fx(); | |||
| carla_register_native_plugin_vex_synth(); | |||
| #ifdef WANT_AUDIOFILE | |||
| // AudioFile | |||
| @@ -111,7 +114,8 @@ struct PluginListManager { | |||
| #ifdef WANT_ZYNADDSUBFX | |||
| // ZynAddSubFX | |||
| carla_register_native_plugin_zynaddsubfx(); | |||
| carla_register_native_plugin_zynaddsubfx_fx(); | |||
| carla_register_native_plugin_zynaddsubfx_synth(); | |||
| #endif | |||
| } | |||