| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,170 @@ | ||
| /* | ||
| * Stutter Juice Plugin | ||
| * Copyright (C) 2014 Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz | ||
| * | ||
| * 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. | ||
| */ | ||
|
|
||
| #ifndef STUTTERJUICEPLUGIN_HPP_INCLUDED | ||
| #define STUTTERJUICEPLUGIN_HPP_INCLUDED | ||
|
|
||
| #include "DistrhoPlugin.hpp" | ||
| #include "CModule.hxx" | ||
|
|
||
|
|
||
| START_NAMESPACE_DISTRHO | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
|
|
||
| class StutterJuicePlugin : public Plugin | ||
| { | ||
| public: | ||
| enum Parameters | ||
| { | ||
| p1 = 0, p2, p3, p4, p5, p6, p7, p8, p9, | ||
| p11, p12, p13, p14, p15, p16, p17, p18, | ||
| p19, p20, p21, p22, p23, p24, p25, p26, | ||
| o1, o2, o3, o4, o5, o6, o7, o8, o9, | ||
| paramCount | ||
| }; | ||
|
|
||
|
|
||
| void prepareOutputParams() { | ||
|
|
||
| for (int i=0; i<6; i++) { | ||
| if (modules[i]->isActive()) { | ||
| outputParams[i] = modules[i]->getOutputParam(); | ||
| } else { | ||
| outputParams[i] = 0; | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void rollLFOs() { | ||
|
|
||
| float bar, tick, tickOffset, sinePos, percentage; | ||
|
|
||
| for (int i=0; i<6; i++) { | ||
| sinePos = modules[i]->getSinePos(); | ||
| float tempoDivider = modules[i]->getTempoDivider(); | ||
| //if (i==4) | ||
| //printf("divider: %i\n", tempoDivider); | ||
| /* sample count for one bar */ | ||
| const TimePos& time = d_getTimePos(); | ||
| bar = ((120.0/(time.bbt.valid ? time.bbt.beatsPerMinute : 120.0))*(d_getSampleRate())); //ONE, two, three, four | ||
| tick = bar/(std::round(params[i][0]*16+2))*tempoDivider; //size of one target wob | ||
| //if (time.bbt.valid) printf("hell yeah!\n"); | ||
| if (time.playing) | ||
| { | ||
| /* if rolling then sync to timepos */ | ||
| tickOffset = time.frame-std::floor(time.frame/tick)*tick; //how much after last tick | ||
|
|
||
| if (tickOffset!=0) { | ||
| //TODO: why do we need this?? | ||
| percentage = tickOffset/tick; | ||
| } else { | ||
| percentage = 0; | ||
| } | ||
| sinePos = (M_PI*2)*percentage; | ||
|
|
||
| if (sinePos>2*M_PI) { | ||
| //TODO: can this ever happen?? | ||
| sinePos = 0; | ||
| } | ||
| } | ||
| else | ||
| { | ||
| /* else just keep on wobblin' */ | ||
| sinePos += (2*M_PI)/(tick); //wtf, but works | ||
| if (sinePos>2*M_PI) { | ||
| sinePos = 0; | ||
| } | ||
| } | ||
| modules[i]->setSinePos(sinePos); | ||
| //printf("sinepos: %f\n", sinePos); | ||
| } | ||
|
|
||
| } | ||
|
|
||
|
|
||
| StutterJuicePlugin(); | ||
| //~StutterJuicePlugin() override; | ||
|
|
||
| protected: | ||
| // ------------------------------------------------------------------- | ||
| // Information | ||
|
|
||
| const char* d_getLabel() const noexcept override | ||
| { | ||
| return "StutterJuice"; | ||
| } | ||
|
|
||
| const char* d_getMaker() const noexcept override | ||
| { | ||
| return "Andre Sklenar"; | ||
| } | ||
|
|
||
| const char* d_getLicense() const noexcept override | ||
| { | ||
| return "GPL v2+"; | ||
| } | ||
|
|
||
| uint32_t d_getVersion() const noexcept override | ||
| { | ||
| return 0x1000; | ||
| } | ||
|
|
||
| long d_getUniqueId() const noexcept override | ||
| { | ||
| return d_cconst('S', 't', 't', 'J'); | ||
| } | ||
|
|
||
| // ------------------------------------------------------------------- | ||
| // Init | ||
|
|
||
| void d_initParameter(uint32_t index, Parameter& parameter) override; | ||
| void d_initProgramName(uint32_t index, d_string& programName) override; | ||
|
|
||
| // ------------------------------------------------------------------- | ||
| // Internal data | ||
|
|
||
| float d_getParameterValue(uint32_t index) const override; | ||
| void d_setParameterValue(uint32_t index, float value) override; | ||
| void d_setProgram(uint32_t index) override; | ||
|
|
||
| // ------------------------------------------------------------------- | ||
| // Process | ||
|
|
||
| void d_activate() override; | ||
| void d_deactivate() override; | ||
| void d_run(const float** inputs, float** outputs, uint32_t frames, const MidiEvent* midiEvents, uint32_t midiEventCount) override; | ||
|
|
||
| // ------------------------------------------------------------------- | ||
|
|
||
| private: | ||
|
|
||
| float params[9][3]; // left-> right, top->bottom | ||
| bool moduleActive[9]; | ||
| float outputParams[9]; | ||
|
|
||
|
|
||
|
|
||
| CModule* modules[9]; | ||
|
|
||
| }; | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
|
|
||
| END_NAMESPACE_DISTRHO | ||
|
|
||
| #endif // TRIGGERJUICE_HPP_INCLUDED |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,165 @@ | ||
| /* | ||
| * Stutter Juice Plugin | ||
| * Copyright (C) 2014 Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz | ||
| * | ||
| * 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 "StutterJuiceUI.hpp" | ||
|
|
||
| using DGL::Point; | ||
|
|
||
| START_NAMESPACE_DISTRHO | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
|
|
||
| StutterJuiceUI::StutterJuiceUI() | ||
| : UI(), | ||
| fAboutWindow(this) | ||
| { | ||
| // background | ||
| fImgBackground = Image(StutterJuiceArtwork::backgroundData, StutterJuiceArtwork::backgroundWidth, StutterJuiceArtwork::backgroundHeight, GL_BGR); | ||
|
|
||
| // overlay | ||
| fImgOverlay = Image(StutterJuiceArtwork::overlayData, StutterJuiceArtwork::overlayWidth, StutterJuiceArtwork::overlayHeight, GL_BGRA); | ||
|
|
||
| // about | ||
| Image imageAbout(StutterJuiceArtwork::aboutData, StutterJuiceArtwork::aboutWidth, StutterJuiceArtwork::aboutHeight, GL_BGRA); | ||
| fAboutWindow.setImage(imageAbout); | ||
|
|
||
| // about button | ||
| Image aboutImageNormal(StutterJuiceArtwork::aboutButtonNormalData, StutterJuiceArtwork::aboutButtonNormalWidth, StutterJuiceArtwork::aboutButtonNormalHeight); | ||
| Image aboutImageHover(StutterJuiceArtwork::aboutButtonHoverData, StutterJuiceArtwork::aboutButtonHoverWidth, StutterJuiceArtwork::aboutButtonHoverHeight); | ||
| fButtonAbout = new ImageButton(this, aboutImageNormal, aboutImageHover, aboutImageHover); | ||
| fButtonAbout->setAbsolutePos(358, 17); | ||
| fButtonAbout->setCallback(this); | ||
|
|
||
| // sliders | ||
| Image sliderImage(StutterJuiceArtwork::sliderData, StutterJuiceArtwork::sliderWidth, StutterJuiceArtwork::sliderHeight); | ||
| Point<int> sliderPosStart(293, 74); | ||
| Point<int> sliderPosEnd(293+11, 74); | ||
|
|
||
| int oX = 130; | ||
| int oY = 93; | ||
| int mX = 357 - oX; | ||
| int mY = 120-oY; | ||
| int mMY = 208 - oY; | ||
| int w = 235 - oX - StutterJuiceArtwork::sliderWidth; | ||
|
|
||
| for (int module=0; module<9; module++) { | ||
| for (int param=0; param<3; param++) { | ||
| sliderPosStart.setX(oX+(module%3)*mX); | ||
| sliderPosStart.setY(oY+(param*mY) + (int) (floor(module/3)*mMY)); | ||
| sliderPosEnd.setX(sliderPosStart.getX() + w); | ||
| sliderPosEnd.setY(sliderPosStart.getY()); | ||
|
|
||
| fSliders[module][param]= new ImageSlider(this, sliderImage); | ||
| fSliders[module][param]->setStartPos(sliderPosStart); | ||
| fSliders[module][param]->setEndPos(sliderPosEnd); | ||
| fSliders[module][param]->setRange(0.0f, 1.0f); | ||
| fSliders[module][param]->setValue(0.0f); | ||
| fSliders[module][param]->setStep(0.125f); | ||
| fSliders[module][param]->setCallback(this); | ||
|
|
||
| } | ||
|
|
||
| outputParams[module] = 0; | ||
| } | ||
|
|
||
| // set default values | ||
| d_programChanged(0); | ||
| } | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
| // DSP Callbacks | ||
|
|
||
| void StutterJuiceUI::d_parameterChanged(uint32_t index, float value) | ||
| { | ||
| if (index<26) { | ||
| int module = index/3; | ||
| int param = index%3; | ||
| fSliders[module][param]->setValue(value); | ||
| } else { | ||
| outputParams[index-26] = value; | ||
| repaint(); | ||
| } | ||
| } | ||
|
|
||
| void StutterJuiceUI::d_programChanged(uint32_t index) | ||
| { | ||
| if (index != 0) | ||
| return; | ||
| } | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
| // Widget Callbacks | ||
|
|
||
| void StutterJuiceUI::imageButtonClicked(ImageButton* button, int) | ||
| { | ||
| if (button != fButtonAbout) | ||
| return; | ||
|
|
||
| fAboutWindow.exec(); | ||
| } | ||
|
|
||
| void StutterJuiceUI::imageSliderDragStarted(ImageSlider* slider) | ||
| { | ||
| for (int module=0; module<9; module++) { | ||
| for (int param=0; param<3; param++) { | ||
| if (slider == fSliders[module][param]) { | ||
| d_editParameter(module*3+param, true); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void StutterJuiceUI::imageSliderDragFinished(ImageSlider* slider) | ||
| { | ||
| for (int module=0; module<9; module++) { | ||
| for (int param=0; param<3; param++) { | ||
| if (slider == fSliders[module][param]) { | ||
| d_editParameter(module*3+param, false); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void StutterJuiceUI::imageSliderValueChanged(ImageSlider* slider, float value) | ||
| { | ||
| for (int module=0; module<9; module++) { | ||
| for (int param=0; param<3; param++) { | ||
| if (slider == fSliders[module][param]) { | ||
| d_setParameterValue(module*3+param, value); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| void StutterJuiceUI::onDisplay() | ||
| { | ||
| fImgBackground.draw(); | ||
|
|
||
| drawLFOs(); | ||
| fImgOverlay.draw(); | ||
| } | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
|
|
||
| UI* createUI() | ||
| { | ||
| return new StutterJuiceUI(); | ||
| } | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
|
|
||
| END_NAMESPACE_DISTRHO |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,128 @@ | ||
| /* | ||
| * Stutter Juice Plugin | ||
| * Copyright (C) 2014 Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz | ||
| * | ||
| * 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. | ||
| */ | ||
|
|
||
| #ifndef STUTTERJUICEUI_HPP_INCLUDED | ||
| #define STUTTERJUICEUI_HPP_INCLUDED | ||
|
|
||
| #include "DistrhoUI.hpp" | ||
|
|
||
| #include "Geometry.hpp" | ||
| #include "ImageAboutWindow.hpp" | ||
| #include "ImageButton.hpp" | ||
| #include "ImageKnob.hpp" | ||
| #include "ImageSlider.hpp" | ||
|
|
||
| #include "StutterJuiceArtwork.hpp" | ||
| #include "StutterJuicePlugin.hpp" | ||
|
|
||
| using DGL::Image; | ||
| using DGL::ImageAboutWindow; | ||
| using DGL::ImageButton; | ||
| using DGL::ImageKnob; | ||
| using DGL::ImageSlider; | ||
| using DGL::Rectangle; | ||
|
|
||
| START_NAMESPACE_DISTRHO | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
|
|
||
| class StutterJuiceUI : public UI, | ||
| public ImageButton::Callback, | ||
| public ImageSlider::Callback | ||
| { | ||
| public: | ||
| StutterJuiceUI(); | ||
|
|
||
| protected: | ||
| // ------------------------------------------------------------------- | ||
| // Information | ||
|
|
||
| uint d_getWidth() const noexcept override | ||
| { | ||
| return StutterJuiceArtwork::backgroundWidth; | ||
| } | ||
|
|
||
| uint d_getHeight() const noexcept override | ||
| { | ||
| return StutterJuiceArtwork::backgroundHeight; | ||
| } | ||
|
|
||
| // ------------------------------------------------------------------- | ||
| // DSP Callbacks | ||
|
|
||
| void d_parameterChanged(uint32_t index, float value) override; | ||
| void d_programChanged(uint32_t index) override; | ||
|
|
||
| // ------------------------------------------------------------------- | ||
| // Widget Callbacks | ||
|
|
||
| void imageButtonClicked(ImageButton* button, int) override; | ||
| void imageSliderDragStarted(ImageSlider* slider) override; | ||
| void imageSliderDragFinished(ImageSlider* slider) override; | ||
| void imageSliderValueChanged(ImageSlider* slider, float value) override; | ||
|
|
||
| void onDisplay() override; | ||
|
|
||
| private: | ||
| Image fImgBackground; | ||
| Image fImgOverlay; | ||
| ImageAboutWindow fAboutWindow; | ||
|
|
||
| float outputParams[9]; | ||
|
|
||
| void drawLFOs() { | ||
| int oX = 18; | ||
| int oY = 67; | ||
| int wX = 223; | ||
| wX /=4; | ||
| int wY = 26; | ||
| int mX = 228; | ||
| int mY = 116; | ||
|
|
||
| wX = 221+2; | ||
| wY = 111; | ||
|
|
||
| // set color | ||
|
|
||
| for (int y=0; y<3; y++) { | ||
| for (int x=0; x<3; x++) { | ||
| if (outputParams[x+y*3]!=0) { | ||
| glColor4f(0.0f, 0.0f, 1.0f, 0.5f - outputParams[x+y*3]/2); | ||
| glBegin(GL_POLYGON); | ||
| glVertex2i(oX+x*mX, oY+y*mY); | ||
| glVertex2i(oX+x*mX, oY+y*mY+wY); | ||
| glVertex2i(oX+x*mX+wX, oY+y*mY+wY); | ||
| glVertex2i(oX+x*mX+wX, oY+y*mY); | ||
| glEnd(); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // reset color | ||
| glColor4f(1.0f, 1.0f, 1.0f, 1.0f); | ||
| } | ||
|
|
||
| //sliders | ||
| ScopedPointer<ImageSlider> fSliders[9][3]; | ||
| ScopedPointer<ImageButton> fButtonAbout; | ||
| }; | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
|
|
||
| END_NAMESPACE_DISTRHO | ||
|
|
||
| #endif // TRIGGERJUICEUI_HPP_INCLUDED |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,71 @@ | ||
| #ifndef CSTREAM_HXX_INCLUDED | ||
| #define CSTREAM_HXX_INCLUDED | ||
|
|
||
| class CStream | ||
| { | ||
|
|
||
| public: | ||
| CStream() { | ||
| sample = 0; | ||
| time = 0; | ||
| state = 0; | ||
| counter = 0; | ||
|
|
||
| } | ||
|
|
||
| void setSr(int sr) { | ||
| sampleRate = sr; | ||
| } | ||
|
|
||
| void open(float nTime) {//in samples | ||
| state = true; | ||
| if (counter<time) { | ||
| counter = time-counter; | ||
| } else { | ||
| counter = 0; | ||
| } | ||
| time = nTime*sampleRate; | ||
| } | ||
|
|
||
| void close(float nTime) {//in samples | ||
| state = false; | ||
| if (counter<time) { | ||
| counter = time-counter; | ||
| } else { | ||
| counter = 0; | ||
| } | ||
| time = nTime*sampleRate; | ||
| } | ||
|
|
||
| void update(float nSample) { | ||
| sample = nSample; | ||
| } | ||
|
|
||
| float run() { | ||
| if (state) { | ||
| if (counter<time) { | ||
| counter++; | ||
| sample*=(counter/time); //linear fade-in | ||
| } else { | ||
| sample*=1; | ||
| } | ||
| } else { | ||
| if (counter<time) { | ||
| counter++; | ||
| sample*=((time-counter)/time); //lineaar fade-out | ||
| } else { | ||
| sample=0; | ||
| } | ||
| } | ||
| return sample; | ||
| } | ||
|
|
||
| private: | ||
| //vars | ||
| float sample; | ||
| float time; | ||
| float counter; | ||
| int sampleRate; | ||
| bool state;//is open? | ||
| }; | ||
| #endif // CSTREAM_HXX_INCLUDED |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| /* | ||
| * Trigger Juice Plugin | ||
| * Copyright (C) 2014 Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz | ||
| * | ||
| * 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. | ||
| */ | ||
|
|
||
| #ifndef DISTRHO_PLUGIN_INFO_H_INCLUDED | ||
| #define DISTRHO_PLUGIN_INFO_H_INCLUDED | ||
|
|
||
| #define DISTRHO_PLUGIN_NAME "TriggerJuice" | ||
|
|
||
| #define DISTRHO_PLUGIN_HAS_UI 1 | ||
| #define DISTRHO_PLUGIN_IS_SYNTH 1 | ||
|
|
||
| #define DISTRHO_PLUGIN_NUM_INPUTS 2 | ||
| #define DISTRHO_PLUGIN_NUM_OUTPUTS 2 | ||
|
|
||
| #define DISTRHO_PLUGIN_WANT_LATENCY 0 | ||
| #define DISTRHO_PLUGIN_WANT_PROGRAMS 1 | ||
| #define DISTRHO_PLUGIN_WANT_STATE 0 | ||
| #define DISTRHO_PLUGIN_WANT_TIMEPOS 1 | ||
|
|
||
| #define DISTRHO_PLUGIN_URI "urn:distrho:TriggerJuice" | ||
|
|
||
| #endif // DISTRHO_PLUGIN_INFO_H_INCLUDED |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| #!/usr/bin/make -f | ||
| # Makefile for DISTRHO Plugins # | ||
| # ---------------------------- # | ||
| # Created by falkTX | ||
| # | ||
|
|
||
| # -------------------------------------------------------------- | ||
| # Project name, used for binaries | ||
|
|
||
| NAME = TriggerJuice | ||
|
|
||
| # -------------------------------------------------------------- | ||
| # Files to build | ||
|
|
||
| OBJS_DSP = \ | ||
| TriggerJuicePlugin.cpp.o | ||
|
|
||
| OBJS_UI = \ | ||
| TriggerJuiceArtwork.cpp.o \ | ||
| TriggerJuiceUI.cpp.o | ||
|
|
||
| # -------------------------------------------------------------- | ||
| # Do some magic | ||
|
|
||
| include ../Makefile.mk | ||
|
|
||
| # -------------------------------------------------------------- | ||
| # Enable all possible plugin types | ||
|
|
||
| ifeq ($(LINUX),true) | ||
| all: jack lv2_sep vst | ||
| else | ||
| all: lv2_sep vst | ||
| endif | ||
|
|
||
| # -------------------------------------------------------------- |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,40 @@ | ||
| /* (Auto-generated binary data file). */ | ||
|
|
||
| #ifndef BINARY_TRIGGERJUICEARTWORK_HPP | ||
| #define BINARY_TRIGGERJUICEARTWORK_HPP | ||
|
|
||
| namespace TriggerJuiceArtwork | ||
| { | ||
| extern const char* aboutData; | ||
| const unsigned int aboutDataSize = 240000; | ||
| const unsigned int aboutWidth = 300; | ||
| const unsigned int aboutHeight = 200; | ||
|
|
||
| extern const char* aboutButtonHoverData; | ||
| const unsigned int aboutButtonHoverDataSize = 5888; | ||
| const unsigned int aboutButtonHoverWidth = 92; | ||
| const unsigned int aboutButtonHoverHeight = 16; | ||
|
|
||
| extern const char* aboutButtonNormalData; | ||
| const unsigned int aboutButtonNormalDataSize = 5888; | ||
| const unsigned int aboutButtonNormalWidth = 92; | ||
| const unsigned int aboutButtonNormalHeight = 16; | ||
|
|
||
| extern const char* backgroundData; | ||
| const unsigned int backgroundDataSize = 365156; | ||
| const unsigned int backgroundWidth = 473; | ||
| const unsigned int backgroundHeight = 193; | ||
|
|
||
| extern const char* knobData; | ||
| const unsigned int knobDataSize = 10404; | ||
| const unsigned int knobWidth = 51; | ||
| const unsigned int knobHeight = 51; | ||
|
|
||
| extern const char* sliderData; | ||
| const unsigned int sliderDataSize = 2600; | ||
| const unsigned int sliderWidth = 26; | ||
| const unsigned int sliderHeight = 25; | ||
| } | ||
|
|
||
| #endif // BINARY_TRIGGERJUICEARTWORK_HPP | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,331 @@ | ||
| /* | ||
| * Trigger Juice Plugin | ||
| * Copyright (C) 2014 Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz | ||
| * | ||
| * 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 "TriggerJuicePlugin.hpp" | ||
| #include <iostream> | ||
|
|
||
|
|
||
|
|
||
| START_NAMESPACE_DISTRHO | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
|
|
||
|
|
||
|
|
||
| TriggerJuicePlugin::TriggerJuicePlugin() | ||
| : Plugin(paramCount, 1, 0) // 1 program, 0 states | ||
| { | ||
| // set default values | ||
| d_setProgram(0); | ||
|
|
||
| // reset | ||
| d_deactivate(); | ||
| } | ||
|
|
||
| TriggerJuicePlugin::~TriggerJuicePlugin() | ||
| { | ||
|
|
||
| } | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
| // Init | ||
|
|
||
| void TriggerJuicePlugin::d_initParameter(uint32_t index, Parameter& parameter) | ||
| { | ||
| switch (index) | ||
| { | ||
| case paramAttack: | ||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | ||
| parameter.name = "Attack"; | ||
| parameter.symbol = "att"; | ||
| parameter.unit = "seconds"; | ||
| parameter.ranges.def = 0.0f; | ||
| parameter.ranges.min = 0.0f; | ||
| parameter.ranges.max = 1.0f; | ||
| break; | ||
|
|
||
| case paramRelease: | ||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | ||
| parameter.name = "Release"; | ||
| parameter.symbol = "rel"; | ||
| parameter.unit = "seconds"; | ||
| parameter.ranges.def = 0.0f; | ||
| parameter.ranges.min = 0.0f; | ||
| parameter.ranges.max = 1.0f; | ||
| break; | ||
|
|
||
| case paramRev: | ||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | ||
| parameter.name = "Reverse"; | ||
| parameter.symbol = "rev"; | ||
| parameter.unit = ""; | ||
| parameter.ranges.def = 0.0f; | ||
| parameter.ranges.min = 0.0f; | ||
| parameter.ranges.max = 1.0f; | ||
| break; | ||
|
|
||
| case paramSplit: | ||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | ||
| parameter.name = "Split"; | ||
| parameter.symbol = "spl"; | ||
| parameter.unit = ""; | ||
| parameter.ranges.def = 0.0f; | ||
| parameter.ranges.min = 0.0f; | ||
| parameter.ranges.max = 1.0f; | ||
| break; | ||
|
|
||
| case paramMS: | ||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | ||
| parameter.name = "M/S"; | ||
| parameter.symbol = "ms"; | ||
| parameter.unit = ""; | ||
| parameter.ranges.def = 0.0f; | ||
| parameter.ranges.min = 0.0f; | ||
| parameter.ranges.max = 1.0f; | ||
| break; | ||
|
|
||
| } | ||
|
|
||
|
|
||
| } | ||
|
|
||
| void TriggerJuicePlugin::d_initProgramName(uint32_t index, d_string& programName) | ||
| { | ||
| if (index != 0) | ||
| return; | ||
|
|
||
| programName = "Default"; | ||
| } | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
| // Internal data | ||
|
|
||
| float TriggerJuicePlugin::d_getParameterValue(uint32_t index) const | ||
| { | ||
| switch (index) | ||
| { | ||
| case paramAttack: | ||
| return attack; | ||
| case paramRelease: | ||
| return release; | ||
| case paramSplit: | ||
| return split; | ||
| case paramRev: | ||
| return rev; | ||
| case paramMS: | ||
| return MS; | ||
| default: | ||
| return 0.0f; | ||
| } | ||
| } | ||
|
|
||
| void TriggerJuicePlugin::d_setParameterValue(uint32_t index, float value) | ||
| { | ||
| switch (index) | ||
| { | ||
| case paramSplit: | ||
| split = value; | ||
| break; | ||
| case paramRev: | ||
| rev = value; | ||
| if (rev<0.5) { | ||
| left.close(d_getSampleRate()/10); right.close(d_getSampleRate()/10); | ||
| } else { | ||
| left.open(d_getSampleRate()/10); right.open(d_getSampleRate()/10); | ||
| } | ||
| break; | ||
| case paramAttack: | ||
| attack = value; | ||
| break; | ||
| case paramRelease: | ||
| release = value; | ||
| break; | ||
| case paramMS: | ||
| MS = value; | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| void TriggerJuicePlugin::d_setProgram(uint32_t index) | ||
| { | ||
| if (index != 0) | ||
| return; | ||
|
|
||
| /* Default parameter values */ | ||
| split = 0.0f; | ||
| rev = 0.0f; | ||
| attack = 0.0f; | ||
| release = 0.0f; | ||
| MS = 0.0f; | ||
|
|
||
| /* Default variable values */ | ||
| attack=release=0; | ||
| rev=split=MS=0; | ||
|
|
||
| left.setSr(d_getSampleRate()); | ||
| right.setSr(d_getSampleRate()); | ||
|
|
||
| //parameter smoothing | ||
| for (int i=0; i<2; i++) { | ||
| sA[i] = 0.99f; | ||
| sB[i] = 1.f - sA[i]; | ||
| sZ[i] = 0; | ||
| } | ||
|
|
||
| /* reset filter values */ | ||
| d_activate(); | ||
| } | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
| // Process | ||
|
|
||
| void TriggerJuicePlugin::d_activate() | ||
| { | ||
| //sinePos = 0; | ||
| } | ||
|
|
||
| void TriggerJuicePlugin::d_deactivate() | ||
| { | ||
| // all values to zero | ||
| } | ||
|
|
||
| void TriggerJuicePlugin::d_run(const float** inputs, float** outputs, uint32_t frames, const MidiEvent* midiEvents, uint32_t midiEventCount) | ||
| { | ||
|
|
||
| for (uint32_t i; i<frames; i++) { | ||
|
|
||
| float inL = inputs[0][i]; | ||
| float inR = inputs[1][i]; | ||
| if (MS<0.5) { | ||
| //stereo mode | ||
| left.update(inL); | ||
| right.update(inR); | ||
| } else { | ||
| //M/S mode | ||
| left.update(inL+inR); | ||
| right.update(inL-inR); | ||
| } | ||
|
|
||
| float audioL = left.run(); | ||
| float audioR = right.run(); | ||
|
|
||
| if (MS>=0.5) { | ||
| // decode from MS | ||
| float mid = audioL; | ||
| float side = audioR; | ||
| audioL = (mid+side)/2; | ||
| audioR = (mid-side)/2; | ||
| } | ||
|
|
||
| outputs[0][i] = audioL; | ||
| outputs[1][i] = audioR; | ||
| } | ||
|
|
||
| int userNote = 64;//TODO | ||
|
|
||
| for (uint32_t i; i<midiEventCount; i++) { | ||
|
|
||
| int mType = midiEvents[i].buf[0] & 0xF0; | ||
| int mChan = midiEvents[i].buf[0] & 0x0F; | ||
| int mNum = midiEvents[i].buf[1]; | ||
| if (mType == 0x90) { | ||
| //NOTE ON | ||
|
|
||
| std::cout << mNum << std::endl; | ||
| int mVelo = midiEvents[i].buf[2]; | ||
| if (mNum == userNote) { | ||
| if (rev<0.5) { | ||
| if (split<0.5) { | ||
| //open both streams | ||
| left.open(attack); | ||
| right.open(attack); | ||
| } else { | ||
| //open just left stream | ||
| left.open(attack); | ||
| } | ||
| } else { | ||
| if (split<0.5) { | ||
| //close both streams | ||
| left.close(attack); | ||
| right.close(attack); | ||
| } else { | ||
| //close just left stream | ||
| left.close(attack); | ||
| } | ||
| } | ||
| } | ||
| if (split>=0.5) { | ||
| if (mNum == userNote+1) { | ||
| if (rev<0.5) { | ||
| //open right stream | ||
| right.open(attack); | ||
| } else { | ||
| //close right stream | ||
| right.close(attack); | ||
| } | ||
| } | ||
|
|
||
| } | ||
| } else if (mType == 0x80) { | ||
| //NOTE OFF | ||
| if (mNum == userNote) { | ||
| if (rev<0.5) { | ||
| if (split<0.5) { | ||
| //close both streams | ||
| left.close(release); | ||
| right.close(release); | ||
| } else { | ||
| //close just left stream | ||
| left.close(release); | ||
| } | ||
| } else { | ||
| if (split<0.5) { | ||
| //open both streams | ||
| left.open(release); | ||
| right.open(release); | ||
| } else { | ||
| //open just left stream | ||
| left.open(release); | ||
| } | ||
| } | ||
| } | ||
| if (split>=0.5) { | ||
| if (mNum == userNote+1) { | ||
| if (rev<0.5) { | ||
| //close right stream | ||
| right.close(release); | ||
| } else { | ||
| //open right stream | ||
| right.open(release); | ||
| } | ||
| } | ||
|
|
||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
|
|
||
| Plugin* createPlugin() | ||
| { | ||
| return new TriggerJuicePlugin(); | ||
| } | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
|
|
||
| END_NAMESPACE_DISTRHO |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,118 @@ | ||
| /* | ||
| * Trigger Juice Plugin | ||
| * Copyright (C) 2014 Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz | ||
| * | ||
| * 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. | ||
| */ | ||
|
|
||
| #ifndef TRIGGERJUICEPLUGIN_HPP_INCLUDED | ||
| #define TRIGGERJUICEPLUGIN_HPP_INCLUDED | ||
|
|
||
| #include "DistrhoPlugin.hpp" | ||
| #include "CStream.hxx" | ||
|
|
||
|
|
||
| START_NAMESPACE_DISTRHO | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
|
|
||
| class TriggerJuicePlugin : public Plugin | ||
| { | ||
| public: | ||
| enum Parameters | ||
| { | ||
| paramAttack = 0, | ||
| paramRelease, | ||
| paramSplit, | ||
| paramRev, | ||
| paramMS, | ||
| paramCount | ||
| }; | ||
|
|
||
| inline float smoothParameter(float in, int axis) { | ||
| sZ[axis] = (in * sB[axis]) + (sZ[axis] * sA[axis]); return sZ[axis]; | ||
| } | ||
|
|
||
|
|
||
|
|
||
| TriggerJuicePlugin(); | ||
| ~TriggerJuicePlugin() override; | ||
|
|
||
| protected: | ||
| // ------------------------------------------------------------------- | ||
| // Information | ||
|
|
||
| const char* d_getLabel() const noexcept override | ||
| { | ||
| return "TriggerJuice"; | ||
| } | ||
|
|
||
| const char* d_getMaker() const noexcept override | ||
| { | ||
| return "Andre Sklenar"; | ||
| } | ||
|
|
||
| const char* d_getLicense() const noexcept override | ||
| { | ||
| return "GPL v2+"; | ||
| } | ||
|
|
||
| uint32_t d_getVersion() const noexcept override | ||
| { | ||
| return 0x1000; | ||
| } | ||
|
|
||
| long d_getUniqueId() const noexcept override | ||
| { | ||
| return d_cconst('T', 'r', 'g', 'J'); | ||
| } | ||
|
|
||
| // ------------------------------------------------------------------- | ||
| // Init | ||
|
|
||
| void d_initParameter(uint32_t index, Parameter& parameter) override; | ||
| void d_initProgramName(uint32_t index, d_string& programName) override; | ||
|
|
||
| // ------------------------------------------------------------------- | ||
| // Internal data | ||
|
|
||
| float d_getParameterValue(uint32_t index) const override; | ||
| void d_setParameterValue(uint32_t index, float value) override; | ||
| void d_setProgram(uint32_t index) override; | ||
|
|
||
| // ------------------------------------------------------------------- | ||
| // Process | ||
|
|
||
| void d_activate() override; | ||
| void d_deactivate() override; | ||
| void d_run(const float** inputs, float** outputs, uint32_t frames, const MidiEvent* midiEvents, uint32_t midiEventCount) override; | ||
|
|
||
| // ------------------------------------------------------------------- | ||
|
|
||
| private: | ||
| CStream left, right; | ||
|
|
||
| float attack, release; | ||
| float rev, split, MS; | ||
|
|
||
|
|
||
|
|
||
| //parameter smoothing, for subOrbitX and subOrbitY | ||
| float sA[2], sB[2], sZ[2]; | ||
| }; | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
|
|
||
| END_NAMESPACE_DISTRHO | ||
|
|
||
| #endif // TRIGGERJUICE_HPP_INCLUDED |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,217 @@ | ||
| /* | ||
| * Trigger Juice Plugin | ||
| * Copyright (C) 2014 Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz | ||
| * | ||
| * 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 "TriggerJuiceUI.hpp" | ||
|
|
||
| using DGL::Point; | ||
|
|
||
| START_NAMESPACE_DISTRHO | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
|
|
||
| TriggerJuiceUI::TriggerJuiceUI() | ||
| : UI(), | ||
| fAboutWindow(this) | ||
| { | ||
| // background | ||
| fImgBackground = Image(TriggerJuiceArtwork::backgroundData, TriggerJuiceArtwork::backgroundWidth, TriggerJuiceArtwork::backgroundHeight, GL_BGRA); | ||
|
|
||
| // about | ||
| Image imageAbout(TriggerJuiceArtwork::aboutData, TriggerJuiceArtwork::aboutWidth, TriggerJuiceArtwork::aboutHeight, GL_BGRA); | ||
| fAboutWindow.setImage(imageAbout); | ||
|
|
||
| // about button | ||
| Image aboutImageNormal(TriggerJuiceArtwork::aboutButtonNormalData, TriggerJuiceArtwork::aboutButtonNormalWidth, TriggerJuiceArtwork::aboutButtonNormalHeight); | ||
| Image aboutImageHover(TriggerJuiceArtwork::aboutButtonHoverData, TriggerJuiceArtwork::aboutButtonHoverWidth, TriggerJuiceArtwork::aboutButtonHoverHeight); | ||
| fButtonAbout = new ImageButton(this, aboutImageNormal, aboutImageHover, aboutImageHover); | ||
| fButtonAbout->setAbsolutePos(358, 17); | ||
| fButtonAbout->setCallback(this); | ||
|
|
||
| // knobs | ||
| Image knobImage(TriggerJuiceArtwork::knobData, TriggerJuiceArtwork::knobWidth, TriggerJuiceArtwork::knobHeight); | ||
|
|
||
| // knob KnobAttack | ||
| fKnobAttack = new ImageKnob(this, knobImage); | ||
| fKnobAttack->setAbsolutePos(42, 77); | ||
| fKnobAttack->setRange(0.0f, 1.0f); | ||
| fKnobAttack->setValue(0.0f); | ||
| fKnobAttack->setRotationAngle(270); | ||
| fKnobAttack->setCallback(this); | ||
|
|
||
| // knob KnobRelease | ||
| fKnobRelease = new ImageKnob(this, knobImage); | ||
| fKnobRelease->setAbsolutePos(139, 77); | ||
| fKnobRelease->setRange(0.0f, 1.0f); | ||
| fKnobRelease->setValue(0.0f); | ||
| fKnobRelease->setRotationAngle(270); | ||
| fKnobRelease->setCallback(this); | ||
|
|
||
| // sliders | ||
| Image sliderImage(TriggerJuiceArtwork::sliderData, TriggerJuiceArtwork::sliderWidth, TriggerJuiceArtwork::sliderHeight); | ||
| Point<int> sliderPosStart(293, 74); | ||
| Point<int> sliderPosEnd(293+11, 74); | ||
|
|
||
| // slider Rev | ||
| fSliderRev = new ImageSlider(this, sliderImage); | ||
| fSliderRev->setStartPos(sliderPosStart); | ||
| fSliderRev->setEndPos(sliderPosEnd); | ||
| fSliderRev->setRange(0.0f, 1.0f); | ||
| fSliderRev->setValue(0.0f); | ||
| fSliderRev->setCallback(this); | ||
|
|
||
| // slider Split | ||
| sliderPosStart.setY(104); | ||
| sliderPosEnd.setY(104); | ||
| fSliderSplit = new ImageSlider(this, sliderImage); | ||
| fSliderSplit->setStartPos(sliderPosStart); | ||
| fSliderSplit->setEndPos(sliderPosEnd); | ||
| fSliderSplit->setRange(0.0f, 1.0f); | ||
| fSliderSplit->setValue(0.0f); | ||
| fSliderSplit->setCallback(this); | ||
|
|
||
| // slider MS | ||
| sliderPosStart.setY(134); | ||
| sliderPosEnd.setY(134); | ||
| fSliderMS = new ImageSlider(this, sliderImage); | ||
| fSliderMS->setStartPos(sliderPosStart); | ||
| fSliderMS->setEndPos(sliderPosEnd); | ||
| fSliderMS->setRange(0.0f, 1.0f); | ||
| fSliderMS->setValue(0.0f); | ||
| fSliderMS->setCallback(this); | ||
|
|
||
| // set default values | ||
| d_programChanged(0); | ||
| } | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
| // DSP Callbacks | ||
|
|
||
| void TriggerJuiceUI::d_parameterChanged(uint32_t index, float value) | ||
| { | ||
| switch (index) | ||
| { | ||
| case TriggerJuicePlugin::paramAttack: | ||
| fKnobAttack->setValue(value); | ||
| break; | ||
| case TriggerJuicePlugin::paramRelease: | ||
| fKnobRelease->setValue(value); | ||
| break; | ||
| case TriggerJuicePlugin::paramRev: | ||
| fSliderRev->setValue(value); | ||
| break; | ||
| case TriggerJuicePlugin::paramSplit: | ||
| fSliderSplit->setValue(value); | ||
| break; | ||
| case TriggerJuicePlugin::paramMS: | ||
| fSliderMS->setValue(value); | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| void TriggerJuiceUI::d_programChanged(uint32_t index) | ||
| { | ||
| if (index != 0) | ||
| return; | ||
|
|
||
| // Default values | ||
| fKnobAttack->setValue(0.0f); | ||
| fKnobRelease->setValue(0.0f); | ||
| fSliderRev->setValue(0.0f); | ||
| fSliderSplit->setValue(0.0f); | ||
| fSliderMS->setValue(0.0f); | ||
| } | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
| // Widget Callbacks | ||
|
|
||
| void TriggerJuiceUI::imageButtonClicked(ImageButton* button, int) | ||
| { | ||
| if (button != fButtonAbout) | ||
| return; | ||
|
|
||
| fAboutWindow.exec(); | ||
| } | ||
|
|
||
| void TriggerJuiceUI::imageKnobDragStarted(ImageKnob* knob) | ||
| { | ||
| if (knob == fKnobAttack) | ||
| d_editParameter(TriggerJuicePlugin::paramAttack, true); | ||
| else if (knob == fKnobRelease) | ||
| d_editParameter(TriggerJuicePlugin::paramRelease, true); | ||
| } | ||
|
|
||
| void TriggerJuiceUI::imageKnobDragFinished(ImageKnob* knob) | ||
| { | ||
| if (knob == fKnobAttack) | ||
| d_editParameter(TriggerJuicePlugin::paramAttack, false); | ||
| else if (knob == fKnobRelease) | ||
| d_editParameter(TriggerJuicePlugin::paramRelease, false); | ||
| } | ||
|
|
||
| void TriggerJuiceUI::imageKnobValueChanged(ImageKnob* knob, float value) | ||
| { | ||
| if (knob == fKnobAttack) | ||
| d_setParameterValue(TriggerJuicePlugin::paramAttack, value); | ||
| else if (knob == fKnobRelease) | ||
| d_setParameterValue(TriggerJuicePlugin::paramRelease, value); | ||
| } | ||
|
|
||
| void TriggerJuiceUI::imageSliderDragStarted(ImageSlider* slider) | ||
| { | ||
| if (slider == fSliderRev) | ||
| d_editParameter(TriggerJuicePlugin::paramRev, true); | ||
| else if (slider == fSliderSplit) | ||
| d_editParameter(TriggerJuicePlugin::paramSplit, true); | ||
| else if (slider == fSliderMS) | ||
| d_editParameter(TriggerJuicePlugin::paramMS, true); | ||
| } | ||
|
|
||
| void TriggerJuiceUI::imageSliderDragFinished(ImageSlider* slider) | ||
| { | ||
| if (slider == fSliderRev) | ||
| d_editParameter(TriggerJuicePlugin::paramRev, false); | ||
| else if (slider == fSliderSplit) | ||
| d_editParameter(TriggerJuicePlugin::paramSplit, false); | ||
| else if (slider == fSliderMS) | ||
| d_editParameter(TriggerJuicePlugin::paramMS, false); | ||
| } | ||
|
|
||
| void TriggerJuiceUI::imageSliderValueChanged(ImageSlider* slider, float value) | ||
| { | ||
| if (slider == fSliderRev) | ||
| d_setParameterValue(TriggerJuicePlugin::paramRev, value); | ||
| else if (slider == fSliderSplit) | ||
| d_setParameterValue(TriggerJuicePlugin::paramSplit, value); | ||
| else if (slider == fSliderMS) | ||
| d_setParameterValue(TriggerJuicePlugin::paramMS, value); | ||
| } | ||
|
|
||
| void TriggerJuiceUI::onDisplay() | ||
| { | ||
| fImgBackground.draw(); | ||
| } | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
|
|
||
| UI* createUI() | ||
| { | ||
| return new TriggerJuiceUI(); | ||
| } | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
|
|
||
| END_NAMESPACE_DISTRHO |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,103 @@ | ||
| /* | ||
| * Trigger Juice Plugin | ||
| * Copyright (C) 2014 Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz | ||
| * | ||
| * 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. | ||
| */ | ||
|
|
||
| #ifndef TRIGGERJUICEUI_HPP_INCLUDED | ||
| #define TRIGGERJUICEUI_HPP_INCLUDED | ||
|
|
||
| #include "DistrhoUI.hpp" | ||
|
|
||
| #include "Geometry.hpp" | ||
| #include "ImageAboutWindow.hpp" | ||
| #include "ImageButton.hpp" | ||
| #include "ImageKnob.hpp" | ||
| #include "ImageSlider.hpp" | ||
|
|
||
| #include "TriggerJuiceArtwork.hpp" | ||
| #include "TriggerJuicePlugin.hpp" | ||
|
|
||
| using DGL::Image; | ||
| using DGL::ImageAboutWindow; | ||
| using DGL::ImageButton; | ||
| using DGL::ImageKnob; | ||
| using DGL::ImageSlider; | ||
| using DGL::Rectangle; | ||
|
|
||
| START_NAMESPACE_DISTRHO | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
|
|
||
| class TriggerJuiceUI : public UI, | ||
| public ImageButton::Callback, | ||
| public ImageKnob::Callback, | ||
| public ImageSlider::Callback | ||
| { | ||
| public: | ||
| TriggerJuiceUI(); | ||
|
|
||
| protected: | ||
| // ------------------------------------------------------------------- | ||
| // Information | ||
|
|
||
| uint d_getWidth() const noexcept override | ||
| { | ||
| return TriggerJuiceArtwork::backgroundWidth; | ||
| } | ||
|
|
||
| uint d_getHeight() const noexcept override | ||
| { | ||
| return TriggerJuiceArtwork::backgroundHeight; | ||
| } | ||
|
|
||
| // ------------------------------------------------------------------- | ||
| // DSP Callbacks | ||
|
|
||
| void d_parameterChanged(uint32_t index, float value) override; | ||
| void d_programChanged(uint32_t index) override; | ||
|
|
||
| // ------------------------------------------------------------------- | ||
| // Widget Callbacks | ||
|
|
||
| void imageButtonClicked(ImageButton* button, int) override; | ||
| void imageKnobDragStarted(ImageKnob* knob) override; | ||
| void imageKnobDragFinished(ImageKnob* knob) override; | ||
| void imageKnobValueChanged(ImageKnob* knob, float value) override; | ||
| void imageSliderDragStarted(ImageSlider* slider) override; | ||
| void imageSliderDragFinished(ImageSlider* slider) override; | ||
| void imageSliderValueChanged(ImageSlider* slider, float value) override; | ||
|
|
||
| void onDisplay() override; | ||
|
|
||
| private: | ||
| float paramX, paramY; | ||
|
|
||
| Image fImgBackground; | ||
| ImageAboutWindow fAboutWindow; | ||
|
|
||
| ScopedPointer<ImageButton> fButtonAbout; | ||
|
|
||
| //knobs | ||
| ScopedPointer<ImageKnob> fKnobAttack, fKnobRelease; | ||
|
|
||
| //sliders | ||
| ScopedPointer<ImageSlider> fSliderRev, fSliderSplit, fSliderMS; | ||
| }; | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
|
|
||
| END_NAMESPACE_DISTRHO | ||
|
|
||
| #endif // TRIGGERJUICEUI_HPP_INCLUDED |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| /* | ||
| * Vector Juice Plugin | ||
| * Copyright (C) 2014 Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz | ||
| * | ||
| * 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. | ||
| */ | ||
|
|
||
| #ifndef DISTRHO_PLUGIN_INFO_H_INCLUDED | ||
| #define DISTRHO_PLUGIN_INFO_H_INCLUDED | ||
|
|
||
| #define DISTRHO_PLUGIN_NAME "VectorJuice" | ||
|
|
||
| #define DISTRHO_PLUGIN_HAS_UI 1 | ||
| #define DISTRHO_PLUGIN_IS_SYNTH 0 | ||
|
|
||
| #define DISTRHO_PLUGIN_NUM_INPUTS 8 | ||
| #define DISTRHO_PLUGIN_NUM_OUTPUTS 2 | ||
|
|
||
| #define DISTRHO_PLUGIN_WANT_LATENCY 0 | ||
| #define DISTRHO_PLUGIN_WANT_PROGRAMS 1 | ||
| #define DISTRHO_PLUGIN_WANT_STATE 0 | ||
| #define DISTRHO_PLUGIN_WANT_TIMEPOS 1 | ||
|
|
||
| #define DISTRHO_PLUGIN_URI "urn:distrho:VectorJuice" | ||
|
|
||
| #endif // DISTRHO_PLUGIN_INFO_H_INCLUDED |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| #!/usr/bin/make -f | ||
| # Makefile for DISTRHO Plugins # | ||
| # ---------------------------- # | ||
| # Created by falkTX | ||
| # | ||
|
|
||
| # -------------------------------------------------------------- | ||
| # Project name, used for binaries | ||
|
|
||
| NAME = VectorJuice | ||
|
|
||
| # -------------------------------------------------------------- | ||
| # Files to build | ||
|
|
||
| OBJS_DSP = \ | ||
| VectorJuicePlugin.cpp.o | ||
|
|
||
| OBJS_UI = \ | ||
| VectorJuiceArtwork.cpp.o \ | ||
| VectorJuiceUI.cpp.o | ||
|
|
||
| # -------------------------------------------------------------- | ||
| # Do some magic | ||
|
|
||
| include ../Makefile.mk | ||
|
|
||
| # -------------------------------------------------------------- | ||
| # Enable all possible plugin types | ||
|
|
||
| ifeq ($(LINUX),true) | ||
| all: jack lv2_sep vst | ||
| else | ||
| all: lv2_sep vst | ||
| endif | ||
|
|
||
| # -------------------------------------------------------------- |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,55 @@ | ||
| /* (Auto-generated binary data file). */ | ||
|
|
||
| #ifndef BINARY_VECTORJUICEARTWORK_HPP | ||
| #define BINARY_VECTORJUICEARTWORK_HPP | ||
|
|
||
| namespace VectorJuiceArtwork | ||
| { | ||
| extern const char* aboutData; | ||
| const unsigned int aboutDataSize = 180000; | ||
| const unsigned int aboutWidth = 300; | ||
| const unsigned int aboutHeight = 200; | ||
|
|
||
| extern const char* aboutButtonHoverData; | ||
| const unsigned int aboutButtonHoverDataSize = 5888; | ||
| const unsigned int aboutButtonHoverWidth = 92; | ||
| const unsigned int aboutButtonHoverHeight = 16; | ||
|
|
||
| extern const char* aboutButtonNormalData; | ||
| const unsigned int aboutButtonNormalDataSize = 5888; | ||
| const unsigned int aboutButtonNormalWidth = 92; | ||
| const unsigned int aboutButtonNormalHeight = 16; | ||
|
|
||
| extern const char* backgroundData; | ||
| const unsigned int backgroundDataSize = 933432; | ||
| const unsigned int backgroundWidth = 712; | ||
| const unsigned int backgroundHeight = 437; | ||
|
|
||
| extern const char* knobData; | ||
| const unsigned int knobDataSize = 10404; | ||
| const unsigned int knobWidth = 51; | ||
| const unsigned int knobHeight = 51; | ||
|
|
||
| extern const char* orbitData; | ||
| const unsigned int orbitDataSize = 4096; | ||
| const unsigned int orbitWidth = 32; | ||
| const unsigned int orbitHeight = 32; | ||
|
|
||
| extern const char* roundletData; | ||
| const unsigned int roundletDataSize = 2500; | ||
| const unsigned int roundletWidth = 25; | ||
| const unsigned int roundletHeight = 25; | ||
|
|
||
| extern const char* sliderData; | ||
| const unsigned int sliderDataSize = 2600; | ||
| const unsigned int sliderWidth = 26; | ||
| const unsigned int sliderHeight = 25; | ||
|
|
||
| extern const char* subOrbitData; | ||
| const unsigned int subOrbitDataSize = 3364; | ||
| const unsigned int subOrbitWidth = 29; | ||
| const unsigned int subOrbitHeight = 29; | ||
| } | ||
|
|
||
| #endif // BINARY_VECTORJUICEARTWORK_HPP | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,391 @@ | ||
| /* | ||
| * Vector Juice Plugin | ||
| * Copyright (C) 2014 Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz | ||
| * | ||
| * 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 "VectorJuicePlugin.hpp" | ||
|
|
||
| START_NAMESPACE_DISTRHO | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
|
|
||
| VectorJuicePlugin::VectorJuicePlugin() | ||
| : Plugin(paramCount, 1, 0) // 1 program, 0 states | ||
| { | ||
| // set default values | ||
| d_setProgram(0); | ||
| } | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
| // Init | ||
|
|
||
| void VectorJuicePlugin::d_initParameter(uint32_t index, Parameter& parameter) | ||
| { | ||
| switch (index) | ||
| { | ||
| case paramX: | ||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | ||
| parameter.name = "X"; | ||
| parameter.symbol = "x"; | ||
| parameter.ranges.def = 0.5f; | ||
| parameter.ranges.min = 0.0f; | ||
| parameter.ranges.max = 1.0f; | ||
| break; | ||
|
|
||
| case paramY: | ||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | ||
| parameter.name = "Y"; | ||
| parameter.symbol = "y"; | ||
| parameter.ranges.def = 0.5f; | ||
| parameter.ranges.min = 0.0f; | ||
| parameter.ranges.max = 1.0f; | ||
| break; | ||
|
|
||
| case paramOrbitSizeX: | ||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | ||
| parameter.name = "Orbit Size X"; | ||
| parameter.symbol = "sizex"; | ||
| parameter.ranges.def = 0.5f; | ||
| parameter.ranges.min = 0.0f; | ||
| parameter.ranges.max = 1.0f; | ||
| break; | ||
|
|
||
| case paramOrbitSizeY: | ||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | ||
| parameter.name = "Orbit Size Y"; | ||
| parameter.symbol = "sizey"; | ||
| parameter.ranges.def = 0.5f; | ||
| parameter.ranges.min = 0.0f; | ||
| parameter.ranges.max = 1.0f; | ||
| break; | ||
|
|
||
| case paramOrbitSpeedX: | ||
| parameter.hints = PARAMETER_IS_AUTOMABLE|PARAMETER_IS_INTEGER; | ||
| parameter.name = "Orbit Speed X"; | ||
| parameter.symbol = "speedx"; | ||
| parameter.ranges.def = 4.0f; | ||
| parameter.ranges.min = 1.0f; | ||
| parameter.ranges.max = 128.0f; | ||
| break; | ||
|
|
||
| case paramOrbitSpeedY: | ||
| parameter.hints = PARAMETER_IS_AUTOMABLE|PARAMETER_IS_INTEGER; | ||
| parameter.name = "Orbit Speed Y"; | ||
| parameter.symbol = "speedy"; | ||
| parameter.ranges.def = 4.0f; | ||
| parameter.ranges.min = 1.0f; | ||
| parameter.ranges.max = 128.0f; | ||
| break; | ||
|
|
||
| case paramSubOrbitSize: | ||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | ||
| parameter.name = "SubOrbit Size"; | ||
| parameter.symbol = "subsize"; | ||
| parameter.ranges.def = 0.5f; | ||
| parameter.ranges.min = 0.0f; | ||
| parameter.ranges.max = 1.0f; | ||
| break; | ||
|
|
||
| case paramSubOrbitSpeed: | ||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | ||
| parameter.name = "SubOrbit Speed"; | ||
| parameter.symbol = "subspeed"; | ||
| parameter.ranges.def = 32.0f; | ||
| parameter.ranges.min = 1.0f; | ||
| parameter.ranges.max = 128.0f; | ||
| break; | ||
|
|
||
| case paramSubOrbitSmooth: | ||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | ||
| parameter.name = "SubOrbit Wave"; | ||
| parameter.symbol = "subwave"; | ||
| parameter.ranges.def = 0.5f; | ||
| parameter.ranges.min = 0.0f; | ||
| parameter.ranges.max = 1.0f; | ||
| break; | ||
|
|
||
| case paramOrbitWaveX: | ||
| parameter.hints = PARAMETER_IS_AUTOMABLE|PARAMETER_IS_INTEGER; | ||
| parameter.name = "Orbit Wave X"; | ||
| parameter.symbol = "wavex"; | ||
| parameter.ranges.def = 3.0f; | ||
| parameter.ranges.min = 1.0f; | ||
| parameter.ranges.max = 4.0f; | ||
| break; | ||
|
|
||
| case paramOrbitWaveY: | ||
| parameter.hints = PARAMETER_IS_AUTOMABLE|PARAMETER_IS_INTEGER; | ||
| parameter.name = "Orbit Wave Y"; | ||
| parameter.symbol = "wavey"; | ||
| parameter.ranges.def = 3.0f; | ||
| parameter.ranges.min = 1.0f; | ||
| parameter.ranges.max = 4.0f; | ||
| break; | ||
|
|
||
| case paramOrbitPhaseX: | ||
| parameter.hints = PARAMETER_IS_AUTOMABLE|PARAMETER_IS_INTEGER; | ||
| parameter.name = "Orbit Phase X"; | ||
| parameter.symbol = "phasex"; | ||
| parameter.ranges.def = 1.0f; | ||
| parameter.ranges.min = 1.0f; | ||
| parameter.ranges.max = 4.0f; | ||
| break; | ||
|
|
||
| case paramOrbitPhaseY: | ||
| parameter.hints = PARAMETER_IS_AUTOMABLE|PARAMETER_IS_INTEGER; | ||
| parameter.name = "Orbit Phase Y"; | ||
| parameter.symbol = "phasey"; | ||
| parameter.ranges.def = 1.0f; | ||
| parameter.ranges.min = 1.0f; | ||
| parameter.ranges.max = 4.0f; | ||
| break; | ||
|
|
||
| case paramOrbitOutX: | ||
| parameter.hints = PARAMETER_IS_OUTPUT; | ||
| parameter.name = "Orbit X"; | ||
| parameter.symbol = "orx"; | ||
| parameter.ranges.def = 0.5f; | ||
| parameter.ranges.min = 0.0f; | ||
| parameter.ranges.max = 1.0f; | ||
| break; | ||
|
|
||
| case paramOrbitOutY: | ||
| parameter.hints = PARAMETER_IS_OUTPUT; | ||
| parameter.name = "Orbit Y"; | ||
| parameter.symbol = "ory"; | ||
| parameter.ranges.def = 0.5f; | ||
| parameter.ranges.min = 0.0f; | ||
| parameter.ranges.max = 1.0f; | ||
| break; | ||
|
|
||
| case paramSubOrbitOutX: | ||
| parameter.hints = PARAMETER_IS_OUTPUT; | ||
| parameter.name = "SubOrbit X"; | ||
| parameter.symbol = "sorx"; | ||
| parameter.ranges.def = 0.5f; | ||
| parameter.ranges.min = 0.0f; | ||
| parameter.ranges.max = 1.0f; | ||
| break; | ||
|
|
||
| case paramSubOrbitOutY: | ||
| parameter.hints = PARAMETER_IS_OUTPUT; | ||
| parameter.name = "SubOrbit Y"; | ||
| parameter.symbol = "sory"; | ||
| parameter.ranges.def = 0.5f; | ||
| parameter.ranges.min = 0.0f; | ||
| parameter.ranges.max = 1.0f; | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| void VectorJuicePlugin::d_initProgramName(uint32_t index, d_string& programName) | ||
| { | ||
| if (index != 0) | ||
| return; | ||
|
|
||
| programName = "Default"; | ||
| } | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
| // Internal data | ||
|
|
||
| float VectorJuicePlugin::d_getParameterValue(uint32_t index) const | ||
| { | ||
| switch (index) | ||
| { | ||
| case paramX: | ||
| return x; | ||
| case paramY: | ||
| return y; | ||
| case paramOrbitSizeX: | ||
| return orbitSizeX; | ||
| case paramOrbitSizeY: | ||
| return orbitSizeY; | ||
| case paramOrbitSpeedX: | ||
| return orbitSpeedX; | ||
| case paramOrbitSpeedY: | ||
| return orbitSpeedY; | ||
| case paramSubOrbitSize: | ||
| return subOrbitSize; | ||
| case paramSubOrbitSpeed: | ||
| return subOrbitSpeed; | ||
| case paramSubOrbitSmooth: | ||
| return subOrbitSmooth; | ||
| case paramOrbitWaveX: | ||
| return orbitWaveX; | ||
| case paramOrbitWaveY: | ||
| return orbitWaveY; | ||
| case paramOrbitPhaseX: | ||
| return orbitPhaseY; | ||
| case paramOrbitPhaseY: | ||
| return orbitPhaseY; | ||
| case paramOrbitOutX: | ||
| return orbitX; | ||
| case paramOrbitOutY: | ||
| return orbitY; | ||
| case paramSubOrbitOutX: | ||
| return subOrbitX; | ||
| case paramSubOrbitOutY: | ||
| return subOrbitY; | ||
| default: | ||
| return 0.0f; | ||
| } | ||
| } | ||
|
|
||
| void VectorJuicePlugin::d_setParameterValue(uint32_t index, float value) | ||
| { | ||
| bool resetPhase = false; | ||
|
|
||
| switch (index) | ||
| { | ||
| case paramX: | ||
| x = value; | ||
| break; | ||
| case paramY: | ||
| y = value; | ||
| break; | ||
| case paramOrbitSizeX: | ||
| orbitSizeX = value; | ||
| break; | ||
| case paramOrbitSizeY: | ||
| orbitSizeY = value; | ||
| break; | ||
| case paramOrbitSpeedX: | ||
| orbitSpeedX = value; | ||
| resetPhase = true; | ||
| break; | ||
| case paramOrbitSpeedY: | ||
| orbitSpeedY = value; | ||
| resetPhase = true; | ||
| break; | ||
| case paramSubOrbitSize: | ||
| subOrbitSize = value; | ||
| break; | ||
| case paramSubOrbitSpeed: | ||
| subOrbitSpeed = value; | ||
| resetPhase = true; | ||
| break; | ||
| case paramSubOrbitSmooth: | ||
| subOrbitSmooth = value; | ||
| break; | ||
| case paramOrbitWaveX: | ||
| orbitWaveX = value; | ||
| break; | ||
| case paramOrbitWaveY: | ||
| orbitWaveY = value; | ||
| break; | ||
| case paramOrbitPhaseX: | ||
| orbitPhaseX = value; | ||
| resetPhase = true; | ||
| break; | ||
| case paramOrbitPhaseY: | ||
| orbitPhaseY = value; | ||
| resetPhase = true; | ||
| break; | ||
| } | ||
|
|
||
| if (resetPhase) | ||
| { | ||
| sinePosX = 0; | ||
| sinePosY = 0; | ||
| sinePos = 0; | ||
| } | ||
| } | ||
|
|
||
| void VectorJuicePlugin::d_setProgram(uint32_t index) | ||
| { | ||
| if (index != 0) | ||
| return; | ||
|
|
||
| /* Default parameter values */ | ||
| x = 0.5f; | ||
| y = 0.5f; | ||
| orbitSizeX = 0.5f; | ||
| orbitSizeY = 0.5f; | ||
| orbitSpeedX = 4.0f; | ||
| orbitSpeedY = 4.0f; | ||
| subOrbitSize = 0.5f; | ||
| subOrbitSpeed = 32.0f; | ||
| subOrbitSmooth = 0.5f; | ||
| orbitWaveX = 3.0f; | ||
| orbitWaveY = 3.0f; | ||
| orbitPhaseX = 1.0f; | ||
| orbitPhaseY = 1.0f; | ||
|
|
||
| /* reset filter values */ | ||
| d_activate(); | ||
| } | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
| // Process | ||
|
|
||
| void VectorJuicePlugin::d_activate() | ||
| { | ||
| /* Default variable values */ | ||
| orbitX=orbitY=orbitTX=orbitTY=0.5; | ||
| subOrbitX=subOrbitY=subOrbitTX=subOrbitTY=0; | ||
| interpolationDivider=200; | ||
| bar=tickX=tickY=percentageX=percentageY=tickOffsetX=0; | ||
| tickOffsetY=sinePosX=sinePosY=tick=percentage=tickOffset=sinePos=0; | ||
| waveBlend=0; | ||
|
|
||
| //parameter smoothing | ||
| for (int i=0; i<2; i++) { | ||
| sA[i] = 0.99f; | ||
| sB[i] = 1.f - sA[i]; | ||
| sZ[i] = 0; | ||
| } | ||
| } | ||
|
|
||
| void VectorJuicePlugin::d_run(const float** inputs, float** outputs, uint32_t frames) | ||
| { | ||
| float out1, out2, tX, tY; | ||
|
|
||
| for (uint32_t i=0; i<frames; i++) { | ||
| //1.41421 -> 1 | ||
| //<0 = 0 | ||
|
|
||
| animate(); | ||
|
|
||
| tX = subOrbitX; | ||
| tY = subOrbitY; | ||
|
|
||
| out1 = inputs[0][i]*tN(1-std::sqrt((tX*tX)+(tY*tY))); | ||
| out2 = inputs[1][i]*tN(1-std::sqrt((tX*tX)+(tY*tY))); | ||
|
|
||
| out1 += inputs[2][i]*tN(1-std::sqrt(((1-tX)*(1-tX))+(tY*tY))); | ||
| out2 += inputs[3][i]*tN(1-std::sqrt(((1-tX)*(1-tX))+(tY*tY))); | ||
|
|
||
| out1 += inputs[4][i]*tN(1-std::sqrt(((1-tX)*(1-tX))+((1-tY)*(1-tY)))); | ||
| out2 += inputs[5][i]*tN(1-std::sqrt(((1-tX)*(1-tX))+((1-tY)*(1-tY)))); | ||
|
|
||
| out1 += inputs[6][i]*tN(1-std::sqrt((tX*tX)+((1-tY)*(1-tY)))); | ||
| out2 += inputs[7][i]*tN(1-std::sqrt((tX*tX)+((1-tY)*(1-tY)))); | ||
|
|
||
| outputs[0][i] = out1; | ||
| outputs[1][i] = out2; | ||
| } | ||
| } | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
|
|
||
| Plugin* createPlugin() | ||
| { | ||
| return new VectorJuicePlugin(); | ||
| } | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
|
|
||
| END_NAMESPACE_DISTRHO |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,236 @@ | ||
| /* | ||
| * Vector Juice Plugin | ||
| * Copyright (C) 2014 Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz | ||
| * | ||
| * 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. | ||
| */ | ||
|
|
||
| #ifndef VECTORJUICEPLUGIN_HPP_INCLUDED | ||
| #define VECTORJUICEPLUGIN_HPP_INCLUDED | ||
|
|
||
| #include "DistrhoPlugin.hpp" | ||
|
|
||
| START_NAMESPACE_DISTRHO | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
|
|
||
| class VectorJuicePlugin : public Plugin | ||
| { | ||
| public: | ||
| enum Parameters | ||
| { | ||
| paramX = 0, | ||
| paramY, | ||
| paramOrbitSizeX, | ||
| paramOrbitSizeY, | ||
| paramOrbitSpeedX, | ||
| paramOrbitSpeedY, | ||
| paramSubOrbitSize, | ||
| paramSubOrbitSpeed, | ||
| paramSubOrbitSmooth, | ||
| paramOrbitWaveX, | ||
| paramOrbitWaveY, | ||
| paramOrbitPhaseX, | ||
| paramOrbitPhaseY, | ||
| paramOrbitOutX, | ||
| paramOrbitOutY, | ||
| paramSubOrbitOutX, | ||
| paramSubOrbitOutY, | ||
| paramCount | ||
| }; | ||
|
|
||
| float smoothParameter(float in, int axis) { | ||
| sZ[axis] = (in * sB[axis]) + (sZ[axis] * sA[axis]); | ||
| return sZ[axis]; | ||
| } | ||
|
|
||
| float getSinePhase(float x) { | ||
| return (-std::sin(x)); | ||
| } | ||
| float getSawPhase(float x) { | ||
| return (-(2/M_PI *std::atan(1/std::tan(x/2)))); | ||
| } | ||
| float getRevSawPhase(float x) { | ||
| return ((2/M_PI *std::atan(1/std::tan(x/2)))); | ||
| } | ||
| float getSquarePhase(float x) { | ||
| return (std::round((std::sin(x)+1)/2)-0.5)*2; | ||
| } | ||
|
|
||
| //saw, sqr, sin, revSaw | ||
| float getBlendedPhase(float x, float wave) | ||
| { | ||
| //wave = 2; | ||
| if (wave>=1 && wave<2) { | ||
| /* saw vs sqr */ | ||
| waveBlend = wave-1; | ||
| return (getSawPhase(x)*(1-waveBlend) + getSquarePhase(x)*waveBlend); | ||
| } else if (wave>=2 && wave<3) { | ||
| /* sqr vs sin */ | ||
| waveBlend = wave-2; | ||
| return (getSquarePhase(x)*(1-waveBlend) + getSinePhase(x)*waveBlend); | ||
| } else if (wave>=3 && wave<=4) { | ||
| /* sin vs revSaw */ | ||
| waveBlend = wave-3; | ||
| return (getSinePhase(x)*(1-waveBlend) + getRevSawPhase(x)*waveBlend); | ||
| } else { | ||
| return 0.0f; | ||
| } | ||
| } | ||
|
|
||
| float tN(float x) | ||
| { | ||
| if (x>0) return x; | ||
| else return 0; | ||
| } | ||
|
|
||
| void animate() | ||
| { | ||
| //sync orbit with frame, bpm | ||
| const TimePos& time = d_getTimePos(); | ||
| bar = ((120.0/(time.bbt.valid ? time.bbt.beatsPerMinute : 120.0))*(d_getSampleRate())); | ||
|
|
||
| int multiplier = 16;//2000*4; | ||
| tickX = bar/(std::round(orbitSpeedX))*multiplier; | ||
| tickY = bar/(std::round(orbitSpeedY))*multiplier; | ||
| tick = bar/(std::round(subOrbitSpeed))*multiplier; | ||
|
|
||
| if (time.playing) | ||
| { | ||
| /* if rolling then sync to timepos */ | ||
| tickOffsetX = time.frame-std::floor(time.frame/tickX)*tickX; | ||
| tickOffsetY = time.frame-std::floor(time.frame/tickY)*tickY; | ||
| tickOffset = time.frame-std::floor(time.frame/tick)*tick; | ||
| percentageX = tickOffsetX/tickX; | ||
| percentageY = tickOffsetY/tickY; | ||
| percentage = tickOffset/tick; | ||
| sinePosX = (M_PI*2)*percentageX; | ||
| sinePosY = (M_PI*2)*percentageY; | ||
| sinePos = (M_PI*2)*percentage; | ||
| } else { | ||
| /* else just keep on wobblin' */ | ||
| sinePosX += (2*M_PI)/(tickX); | ||
| sinePosY += (2*M_PI)/(tickY); | ||
| sinePos += (M_PI)/(tick); | ||
| if (sinePosX>2*M_PI) { | ||
| sinePosX = 0; | ||
| } | ||
| if (sinePosY>2*M_PI) { | ||
| sinePosY = 0; | ||
| } | ||
| if (sinePos>2*M_PI) { | ||
| sinePos = 0; | ||
| } | ||
| } | ||
|
|
||
| //0..1 | ||
| //0..3 | ||
| //0, 1, 2, 3 | ||
| //* 0.25 | ||
| //0, 0.25, 0.5, 0.75 | ||
|
|
||
| float tempPhaseX = std::round(orbitPhaseX)*0.25-0.25; | ||
| float tempPhaseY = std::round(orbitPhaseY)*0.25-0.25; | ||
|
|
||
| orbitX = x+getBlendedPhase(sinePosX + tempPhaseX*(2*M_PI), std::round(orbitWaveX))*(orbitSizeX/2); | ||
| orbitY = y+getBlendedPhase(sinePosY+M_PI/2 + tempPhaseY*(2*M_PI), std::round(orbitWaveY))*(orbitSizeY/2); | ||
| subOrbitX = smoothParameter(orbitX+getBlendedPhase(sinePos, 3)*(subOrbitSize/3), 0); | ||
| subOrbitY = smoothParameter(orbitY+getBlendedPhase(sinePos+M_PI/2, 3)*(subOrbitSize/3), 1); | ||
| if (orbitX<0) orbitX=0; | ||
| if (orbitX>1) orbitX=1; | ||
| if (orbitY<0) orbitY=0; | ||
| if (orbitY>1) orbitY=1; | ||
|
|
||
| if (subOrbitX<0) subOrbitX=0; | ||
| if (subOrbitX>1) subOrbitX=1; | ||
| if (subOrbitY<0) subOrbitY=0; | ||
| if (subOrbitY>1) subOrbitY=1; | ||
| } | ||
|
|
||
| VectorJuicePlugin(); | ||
|
|
||
| protected: | ||
| // ------------------------------------------------------------------- | ||
| // Information | ||
|
|
||
| const char* d_getLabel() const noexcept override | ||
| { | ||
| return "VectorJuice"; | ||
| } | ||
|
|
||
| const char* d_getMaker() const noexcept override | ||
| { | ||
| return "Andre Sklenar"; | ||
| } | ||
|
|
||
| const char* d_getLicense() const noexcept override | ||
| { | ||
| return "GPL v2+"; | ||
| } | ||
|
|
||
| uint32_t d_getVersion() const noexcept override | ||
| { | ||
| return 0x1000; | ||
| } | ||
|
|
||
| long d_getUniqueId() const noexcept override | ||
| { | ||
| return d_cconst('V', 'e', 'c', 'J'); | ||
| } | ||
|
|
||
| // ------------------------------------------------------------------- | ||
| // Init | ||
|
|
||
| void d_initParameter(uint32_t index, Parameter& parameter) override; | ||
| void d_initProgramName(uint32_t index, d_string& programName) override; | ||
|
|
||
| // ------------------------------------------------------------------- | ||
| // Internal data | ||
|
|
||
| float d_getParameterValue(uint32_t index) const override; | ||
| void d_setParameterValue(uint32_t index, float value) override; | ||
| void d_setProgram(uint32_t index) override; | ||
|
|
||
| // ------------------------------------------------------------------- | ||
| // Process | ||
|
|
||
| void d_activate() override; | ||
| void d_run(const float** inputs, float** outputs, uint32_t frames) override; | ||
|
|
||
| // ------------------------------------------------------------------- | ||
|
|
||
| private: | ||
| float x, y; | ||
| float orbitX, orbitY; | ||
| float orbitTX, orbitTY; //targetX and targetY for interpolation | ||
| float subOrbitX, subOrbitY; | ||
| float subOrbitTX, subOrbitTY; | ||
| float subOrbitSpeed, subOrbitSize, orbitSpeedX, orbitSpeedY; | ||
| float orbitSizeX, orbitSizeY; | ||
| float interpolationDivider; | ||
|
|
||
| float bar, tickX, tickY, percentageX, percentageY, tickOffsetX, tickOffsetY; | ||
| float sinePosX, sinePosY, tick, percentage, tickOffset, sinePos; | ||
|
|
||
| float orbitWaveX, orbitWaveY, subOrbitSmooth, waveBlend; | ||
| float orbitPhaseX, orbitPhaseY; | ||
|
|
||
| //parameter smoothing, for subOrbitX and subOrbitY | ||
| float sA[2], sB[2], sZ[2]; | ||
| }; | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
|
|
||
| END_NAMESPACE_DISTRHO | ||
|
|
||
| #endif // VECTORJUICE_HPP_INCLUDED |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,115 @@ | ||
| /* | ||
| * Vector Juice Plugin | ||
| * Copyright (C) 2014 Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz | ||
| * | ||
| * 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. | ||
| */ | ||
|
|
||
| #ifndef VECTORJUICEUI_HPP_INCLUDED | ||
| #define VECTORJUICEUI_HPP_INCLUDED | ||
|
|
||
| #include "DistrhoUI.hpp" | ||
|
|
||
| #include "ImageAboutWindow.hpp" | ||
| #include "ImageButton.hpp" | ||
| #include "ImageKnob.hpp" | ||
| #include "ImageSlider.hpp" | ||
|
|
||
| #include "VectorJuiceArtwork.hpp" | ||
|
|
||
| using DGL::Image; | ||
| using DGL::ImageAboutWindow; | ||
| using DGL::ImageButton; | ||
| using DGL::ImageKnob; | ||
| using DGL::ImageSlider; | ||
|
|
||
| START_NAMESPACE_DISTRHO | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
|
|
||
| class VectorJuiceUI : public UI, | ||
| public ImageButton::Callback, | ||
| public ImageKnob::Callback, | ||
| public ImageSlider::Callback | ||
| { | ||
| public: | ||
| VectorJuiceUI(); | ||
|
|
||
| protected: | ||
| // ------------------------------------------------------------------- | ||
| // Information | ||
|
|
||
| uint d_getWidth() const noexcept override | ||
| { | ||
| return VectorJuiceArtwork::backgroundWidth; | ||
| } | ||
|
|
||
| uint d_getHeight() const noexcept override | ||
| { | ||
| return VectorJuiceArtwork::backgroundHeight; | ||
| } | ||
|
|
||
| // ------------------------------------------------------------------- | ||
| // DSP Callbacks | ||
|
|
||
| void d_parameterChanged(uint32_t index, float value) override; | ||
| void d_programChanged(uint32_t index) override; | ||
|
|
||
| // ------------------------------------------------------------------- | ||
| // Widget Callbacks | ||
|
|
||
| void imageButtonClicked(ImageButton* button, int) override; | ||
| void imageKnobDragStarted(ImageKnob* knob) override; | ||
| void imageKnobDragFinished(ImageKnob* knob) override; | ||
| void imageKnobValueChanged(ImageKnob* knob, float value) override; | ||
| void imageSliderDragStarted(ImageSlider* slider) override; | ||
| void imageSliderDragFinished(ImageSlider* slider) override; | ||
| void imageSliderValueChanged(ImageSlider* slider, float value) override; | ||
|
|
||
| void onDisplay() override; | ||
| bool onMouse(const MouseEvent&) override; | ||
| bool onMotion(const MotionEvent&) override; | ||
|
|
||
| private: | ||
| float paramX, paramY; | ||
|
|
||
| Image fImgBackground; | ||
| Image fImgRoundlet; | ||
| Image fImgOrbit; | ||
| Image fImgSubOrbit; | ||
| ImageAboutWindow fAboutWindow; | ||
|
|
||
| ScopedPointer<ImageButton> fButtonAbout; | ||
|
|
||
| //knobs | ||
| ScopedPointer<ImageKnob> fKnobOrbitSpeedX, fKnobOrbitSpeedY, fKnobOrbitSizeX, fKnobOrbitSizeY; | ||
| ScopedPointer<ImageKnob> fKnobSubOrbitSpeed, fKnobSubOrbitSize, fKnobSubOrbitSmooth; | ||
|
|
||
| //sliders | ||
| ScopedPointer<ImageSlider> fSliderOrbitWaveX, fSliderOrbitWaveY; | ||
| ScopedPointer<ImageSlider> fSliderOrbitPhaseX, fSliderOrbitPhaseY; | ||
|
|
||
| // needed for XY canvas handling | ||
| bool fDragging; | ||
| bool fDragValid; | ||
| int fLastX; | ||
| int fLastY; | ||
| DGL::Rectangle<int> fCanvasArea; | ||
| float orbitX, orbitY, subOrbitX, subOrbitY; | ||
| }; | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
|
|
||
| END_NAMESPACE_DISTRHO | ||
|
|
||
| #endif // VECTORJUICEUI_HPP_INCLUDED |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| /* | ||
| * Wobble Juice Plugin | ||
| * Copyright (C) 2014 Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz | ||
| * | ||
| * 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. | ||
| */ | ||
|
|
||
| #ifndef DISTRHO_PLUGIN_INFO_H_INCLUDED | ||
| #define DISTRHO_PLUGIN_INFO_H_INCLUDED | ||
|
|
||
| #define DISTRHO_PLUGIN_NAME "WobbleJuice" | ||
|
|
||
| #define DISTRHO_PLUGIN_HAS_UI 1 | ||
| #define DISTRHO_PLUGIN_IS_SYNTH 0 | ||
|
|
||
| #define DISTRHO_PLUGIN_NUM_INPUTS 2 | ||
| #define DISTRHO_PLUGIN_NUM_OUTPUTS 2 | ||
|
|
||
| #define DISTRHO_PLUGIN_WANT_LATENCY 0 | ||
| #define DISTRHO_PLUGIN_WANT_PROGRAMS 1 | ||
| #define DISTRHO_PLUGIN_WANT_STATE 0 | ||
| #define DISTRHO_PLUGIN_WANT_TIMEPOS 1 | ||
|
|
||
| #define DISTRHO_PLUGIN_URI "urn:distrho:WobbleJuice" | ||
|
|
||
| #endif // DISTRHO_PLUGIN_INFO_H_INCLUDED |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| #!/usr/bin/make -f | ||
| # Makefile for DISTRHO Plugins # | ||
| # ---------------------------- # | ||
| # Created by falkTX | ||
| # | ||
|
|
||
| # -------------------------------------------------------------- | ||
| # Project name, used for binaries | ||
|
|
||
| NAME = WobbleJuice | ||
|
|
||
| # -------------------------------------------------------------- | ||
| # Files to build | ||
|
|
||
| OBJS_DSP = \ | ||
| WobbleJuicePlugin.cpp.o | ||
|
|
||
| OBJS_UI = \ | ||
| WobbleJuiceArtwork.cpp.o \ | ||
| WobbleJuiceUI.cpp.o | ||
|
|
||
| # -------------------------------------------------------------- | ||
| # Do some magic | ||
|
|
||
| include ../Makefile.mk | ||
|
|
||
| # -------------------------------------------------------------- | ||
| # Enable all possible plugin types | ||
|
|
||
| ifeq ($(LINUX),true) | ||
| all: jack lv2_sep vst | ||
| else | ||
| all: lv2_sep vst | ||
| endif | ||
|
|
||
| # -------------------------------------------------------------- |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| /* (Auto-generated binary data file). */ | ||
|
|
||
| #ifndef BINARY_WOBBLEJUICEARTWORK_HPP | ||
| #define BINARY_WOBBLEJUICEARTWORK_HPP | ||
|
|
||
| namespace WobbleJuiceArtwork | ||
| { | ||
| extern const char* aboutData; | ||
| const unsigned int aboutDataSize = 180000; | ||
| const unsigned int aboutWidth = 300; | ||
| const unsigned int aboutHeight = 200; | ||
|
|
||
| extern const char* aboutButtonHoverData; | ||
| const unsigned int aboutButtonHoverDataSize = 5888; | ||
| const unsigned int aboutButtonHoverWidth = 92; | ||
| const unsigned int aboutButtonHoverHeight = 16; | ||
|
|
||
| extern const char* aboutButtonNormalData; | ||
| const unsigned int aboutButtonNormalDataSize = 5888; | ||
| const unsigned int aboutButtonNormalWidth = 92; | ||
| const unsigned int aboutButtonNormalHeight = 16; | ||
|
|
||
| extern const char* backgroundData; | ||
| const unsigned int backgroundDataSize = 450000; | ||
| const unsigned int backgroundWidth = 500; | ||
| const unsigned int backgroundHeight = 300; | ||
|
|
||
| extern const char* knobData; | ||
| const unsigned int knobDataSize = 12544; | ||
| const unsigned int knobWidth = 56; | ||
| const unsigned int knobHeight = 56; | ||
| } | ||
|
|
||
| #endif // BINARY_WOBBLEJUICEARTWORK_HPP | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,243 @@ | ||
| /* | ||
| * Wobble Juice Plugin | ||
| * Copyright (C) 2014 Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz | ||
| * | ||
| * 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 "WobbleJuicePlugin.hpp" | ||
|
|
||
| START_NAMESPACE_DISTRHO | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
|
|
||
| WobbleJuicePlugin::WobbleJuicePlugin() | ||
| : Plugin(paramCount, 1, 0) // 1 program, 0 states | ||
| { | ||
| // set default values | ||
| d_setProgram(0); | ||
| } | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
| // Init | ||
|
|
||
| void WobbleJuicePlugin::d_initParameter(uint32_t index, Parameter& parameter) | ||
| { | ||
| switch (index) | ||
| { | ||
| case paramDivision: | ||
| parameter.hints = PARAMETER_IS_AUTOMABLE|PARAMETER_IS_INTEGER; | ||
| parameter.name = "Division"; | ||
| parameter.symbol = "div"; | ||
| parameter.unit = "x"; | ||
| parameter.ranges.def = 4.0f; | ||
| parameter.ranges.min = 1.0f; | ||
| parameter.ranges.max = 16.0f; | ||
| break; | ||
| case paramReso: | ||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | ||
| parameter.name = "Resonance"; | ||
| parameter.symbol = "reso"; | ||
| parameter.unit = ""; | ||
| parameter.ranges.def = 0.1f; | ||
| parameter.ranges.min = 0.0f; | ||
| parameter.ranges.max = 0.2f; | ||
| break; | ||
| case paramRange: | ||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | ||
| parameter.name = "Range"; | ||
| parameter.symbol = "rng"; | ||
| parameter.unit = "Hz"; | ||
| parameter.ranges.def = 16000.0f; | ||
| parameter.ranges.min = 500.0f; | ||
| parameter.ranges.max = 16000.0f; | ||
| break; | ||
| case paramPhase: | ||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | ||
| parameter.name = "Phase"; | ||
| parameter.symbol = "phs"; | ||
| parameter.unit = "Deg"; | ||
| parameter.ranges.def = 0.0f; | ||
| parameter.ranges.min = -1.0f; | ||
| parameter.ranges.max = 1.0f; | ||
| break; | ||
| case paramWave: | ||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | ||
| parameter.name = "Wave"; | ||
| parameter.symbol = "wav"; | ||
| parameter.unit = ""; | ||
| parameter.ranges.def = 2.0f; | ||
| parameter.ranges.min = 1.0f; | ||
| parameter.ranges.max = 4.0f; | ||
| break; | ||
| case paramDrive: | ||
| parameter.hints = PARAMETER_IS_AUTOMABLE; | ||
| parameter.name = "Drive"; | ||
| parameter.symbol = "drv"; | ||
| parameter.unit = ""; | ||
| parameter.ranges.def = 0.5f; | ||
| parameter.ranges.min = 0.0f; | ||
| parameter.ranges.max = 1.0f; | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| void WobbleJuicePlugin::d_initProgramName(uint32_t index, d_string& programName) | ||
| { | ||
| if (index != 0) | ||
| return; | ||
|
|
||
| programName = "Default"; | ||
| } | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
| // Internal data | ||
|
|
||
| float WobbleJuicePlugin::d_getParameterValue(uint32_t index) const | ||
| { | ||
| switch (index) | ||
| { | ||
| case paramDivision: | ||
| return division; | ||
| case paramReso: | ||
| return reso; | ||
| case paramRange: | ||
| return range; | ||
| case paramPhase: | ||
| return phase; | ||
| case paramWave: | ||
| return wave; | ||
| case paramDrive: | ||
| return drive; | ||
| default: | ||
| return 0.0f; | ||
| } | ||
| } | ||
|
|
||
| void WobbleJuicePlugin::d_setParameterValue(uint32_t index, float value) | ||
| { | ||
| switch (index) | ||
| { | ||
| case paramDivision: | ||
| division = value; | ||
| break; | ||
| case paramReso: | ||
| reso = value; | ||
| break; | ||
| case paramRange: | ||
| range = value; | ||
| break; | ||
| case paramPhase: | ||
| phase = value; | ||
| break; | ||
| case paramWave: | ||
| wave = value; | ||
| break; | ||
| case paramDrive: | ||
| drive = value; | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| void WobbleJuicePlugin::d_setProgram(uint32_t index) | ||
| { | ||
| if (index != 0) | ||
| return; | ||
|
|
||
| /* Default parameter values */ | ||
| division = 4.0f; | ||
| reso = 0.1f; | ||
| range = 16000.0f; | ||
| phase = 0.0f; | ||
| wave = 2.0f; | ||
| drive = 0.5f; | ||
|
|
||
| /* Default variable values */ | ||
| bar=tick=tickOffset=percentage=phaseOffset=currentPhaseL=0.0f; | ||
| currentPhaseR=posL=posR=cutoffL=cutoffR=0.0f; | ||
| waveType=2.0f; | ||
|
|
||
| /* reset filter values */ | ||
| d_activate(); | ||
| } | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
| // Process | ||
|
|
||
| void WobbleJuicePlugin::d_activate() | ||
| { | ||
| sinePos = 0.0; | ||
| } | ||
|
|
||
| void WobbleJuicePlugin::d_run(const float** inputs, float** outputs, uint32_t frames) | ||
| { | ||
| //fetch the timepos struct from host; | ||
| const TimePos& time(d_getTimePos()); | ||
|
|
||
| /* sample count for one bar */ | ||
| bar = ((120.0/(time.bbt.valid ? time.bbt.beatsPerMinute : 120.0))*(d_getSampleRate())); //ONE, two, three, four | ||
| tick = bar/(std::round(division)); //size of one target wob | ||
| phaseOffset = phase*M_PI; //2pi = 1 whole cycle | ||
|
|
||
| /* if rolling then sync to timepos */ | ||
| if (time.playing) | ||
| { | ||
| tickOffset = time.frame-std::floor(time.frame/tick)*tick; //how much after last tick | ||
|
|
||
| if (tickOffset!=0) { | ||
| //TODO: why do we need this?? | ||
| percentage = tickOffset/tick; | ||
| } else { | ||
| percentage = 0; | ||
| } | ||
| sinePos = (M_PI*2)*percentage; | ||
|
|
||
| if (sinePos>2*M_PI) { | ||
| //TODO: can this ever happen?? | ||
| sinePos = 0; | ||
| } | ||
| } | ||
| /* else just keep on wobblin' */ | ||
| else | ||
| { | ||
| sinePos += (M_PI)/(tick/2000); //wtf, but works | ||
| if (sinePos>2*M_PI) { | ||
| sinePos = 0; | ||
| } | ||
| } | ||
|
|
||
| /* phase of 0..1 filter = 500..16k */ | ||
| currentPhaseL = getBlendedPhase(sinePos+phaseOffset, wave); | ||
| currentPhaseR = getBlendedPhase(sinePos-phaseOffset, wave); | ||
|
|
||
| /* logarithmic */ | ||
| cutoffL = std::exp((std::log(range)-std::log(500))*currentPhaseL+std::log(500)); | ||
| cutoffR = std::exp((std::log(range)-std::log(500))*currentPhaseR+std::log(500)); | ||
|
|
||
| //output filtered signal | ||
| filterL.recalc(cutoffL, reso*4, d_getSampleRate(), drive); | ||
| filterR.recalc(cutoffR, reso*4, d_getSampleRate(), drive); | ||
| filterL.process(frames, inputs[0], outputs[0]); | ||
| filterR.process(frames, inputs[1], outputs[1]); | ||
| } | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
|
|
||
| Plugin* createPlugin() | ||
| { | ||
| return new WobbleJuicePlugin(); | ||
| } | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
|
|
||
| END_NAMESPACE_DISTRHO |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,142 @@ | ||
| /* | ||
| * Wobble Juice Plugin | ||
| * Copyright (C) 2014 Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz | ||
| * | ||
| * 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. | ||
| */ | ||
|
|
||
| #ifndef WOBBLEJUICEPLUGIN_HPP_INCLUDED | ||
| #define WOBBLEJUICEPLUGIN_HPP_INCLUDED | ||
|
|
||
| #include "DistrhoPlugin.hpp" | ||
| #include "moogVCF.hxx" | ||
|
|
||
| START_NAMESPACE_DISTRHO | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
|
|
||
| class WobbleJuicePlugin : public Plugin | ||
| { | ||
| public: | ||
| enum Parameters | ||
| { | ||
| paramDivision = 0, | ||
| paramReso, | ||
| paramRange, | ||
| paramPhase, | ||
| paramWave, | ||
| paramDrive, | ||
| paramCount | ||
| }; | ||
|
|
||
| float getSinePhase(float x) { | ||
| return ((-std::cos(x)+1)/2); | ||
| } | ||
| float getSawPhase(float x) { | ||
| return (-((2/M_PI * std::atan(1/std::tan(x/2)))-1)/2); | ||
| } | ||
| float getRevSawPhase(float x) { | ||
| return (((2/M_PI * std::atan(1/std::tan(x/2)))+1)/2); | ||
| } | ||
| float getSquarePhase(float x) { | ||
| return (std::round((std::sin(x)+1)/2)); | ||
| } | ||
|
|
||
| //saw, sqr, sin, revSaw | ||
| float getBlendedPhase(float x, float wave) | ||
| { | ||
| //wave = 2; | ||
| if (wave>=1 && wave<2) { | ||
| /* saw vs sqr */ | ||
| waveBlend = wave-1; | ||
| return (getSawPhase(x)*(1-waveBlend) + getSquarePhase(x)*waveBlend); | ||
| } else if (wave>=2 && wave<3) { | ||
| /* sqr vs sin */ | ||
| waveBlend = wave-2; | ||
| return (getSquarePhase(x)*(1-waveBlend) + getSinePhase(x)*waveBlend); | ||
| } else if (wave>=3 && wave<=4) { | ||
| /* sin vs revSaw */ | ||
| waveBlend = wave-3; | ||
| return (getSinePhase(x)*(1-waveBlend) + getRevSawPhase(x)*waveBlend); | ||
| } else { | ||
| return 0.0f; | ||
| } | ||
| } | ||
|
|
||
| WobbleJuicePlugin(); | ||
|
|
||
| protected: | ||
| // ------------------------------------------------------------------- | ||
| // Information | ||
|
|
||
| const char* d_getLabel() const noexcept override | ||
| { | ||
| return "WobbleJuice"; | ||
| } | ||
|
|
||
| const char* d_getMaker() const noexcept override | ||
| { | ||
| return "Andre Sklenar"; | ||
| } | ||
|
|
||
| const char* d_getLicense() const noexcept override | ||
| { | ||
| return "GPL v2+"; | ||
| } | ||
|
|
||
| uint32_t d_getVersion() const noexcept override | ||
| { | ||
| return 0x1000; | ||
| } | ||
|
|
||
| long d_getUniqueId() const noexcept override | ||
| { | ||
| return d_cconst('W', 'b', 'l', 'J'); | ||
| } | ||
|
|
||
| // ------------------------------------------------------------------- | ||
| // Init | ||
|
|
||
| void d_initParameter(uint32_t index, Parameter& parameter) override; | ||
| void d_initProgramName(uint32_t index, d_string& programName) override; | ||
|
|
||
| // ------------------------------------------------------------------- | ||
| // Internal data | ||
|
|
||
| float d_getParameterValue(uint32_t index) const override; | ||
| void d_setParameterValue(uint32_t index, float value) override; | ||
| void d_setProgram(uint32_t index) override; | ||
|
|
||
| // ------------------------------------------------------------------- | ||
| // Process | ||
|
|
||
| void d_activate() override; | ||
| void d_run(const float** inputs, float** outputs, uint32_t frames) override; | ||
|
|
||
| // ------------------------------------------------------------------- | ||
|
|
||
| private: | ||
| MoogVCF filterL, filterR; | ||
| float division, reso, range, phase, wave, drive; //parameters | ||
| float bar, tick, tickOffset, percentage, phaseOffset, currentPhaseL, currentPhaseR, posL, posR, cutoffL, cutoffR; | ||
| double sinePos; | ||
| float waveType, waveBlend; | ||
|
|
||
| DISTRHO_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(WobbleJuicePlugin) | ||
| }; | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
|
|
||
| END_NAMESPACE_DISTRHO | ||
|
|
||
| #endif // WOBBLEJUICE_HPP_INCLUDED |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,181 @@ | ||
| /* | ||
| * Wobble Juice Plugin | ||
| * Copyright (C) 2014 Andre Sklenar <andre.sklenar@gmail.com>, www.juicelab.cz | ||
| * | ||
| * 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 "WobbleJuicePlugin.hpp" | ||
| #include "WobbleJuiceUI.hpp" | ||
|
|
||
| START_NAMESPACE_DISTRHO | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
|
|
||
| WobbleJuiceUI::WobbleJuiceUI() | ||
| : UI(), | ||
| fAboutWindow(this) | ||
| { | ||
| // background | ||
| fImgBackground = Image(WobbleJuiceArtwork::backgroundData, WobbleJuiceArtwork::backgroundWidth, WobbleJuiceArtwork::backgroundHeight, GL_BGR); | ||
|
|
||
| // about | ||
| Image aboutImage(WobbleJuiceArtwork::aboutData, WobbleJuiceArtwork::aboutWidth, WobbleJuiceArtwork::aboutHeight, GL_BGR); | ||
| fAboutWindow.setImage(aboutImage); | ||
|
|
||
| // knobs | ||
| Image knobImage(WobbleJuiceArtwork::knobData, WobbleJuiceArtwork::knobWidth, WobbleJuiceArtwork::knobHeight); | ||
|
|
||
| // knob Division | ||
| fKnobDivision = new ImageKnob(this, knobImage, ImageKnob::Vertical, WobbleJuicePlugin::paramDivision); | ||
| fKnobDivision->setAbsolutePos(222, 74); | ||
| fKnobDivision->setRotationAngle(270); | ||
| fKnobDivision->setRange(1.0f, 16.0f); | ||
| fKnobDivision->setDefault(4.0f); | ||
| fKnobDivision->setStep(1.0f); | ||
| fKnobDivision->setCallback(this); | ||
|
|
||
| // knob Resonance | ||
| fKnobResonance = new ImageKnob(this, knobImage, ImageKnob::Vertical, WobbleJuicePlugin::paramReso); | ||
| fKnobResonance->setAbsolutePos(222, 199); | ||
| fKnobResonance->setRotationAngle(270); | ||
| fKnobResonance->setRange(0.0f, 0.2f); | ||
| fKnobResonance->setDefault(0.1f); | ||
| fKnobResonance->setCallback(this); | ||
|
|
||
| // knob Range | ||
| fKnobRange = new ImageKnob(this, knobImage, ImageKnob::Vertical, WobbleJuicePlugin::paramRange); | ||
| fKnobRange->setAbsolutePos(77, 199); | ||
| fKnobRange->setRotationAngle(270); | ||
| fKnobRange->setRange(500.0f, 16000.0f); | ||
| fKnobRange->setDefault(16000.0f); | ||
| fKnobRange->setCallback(this); | ||
|
|
||
| // knob Phase | ||
| fKnobPhase = new ImageKnob(this, knobImage, ImageKnob::Vertical, WobbleJuicePlugin::paramPhase); | ||
| fKnobPhase->setAbsolutePos(362, 74); | ||
| fKnobPhase->setRotationAngle(270); | ||
| fKnobPhase->setRange(-1.0f, 1.0f); | ||
| fKnobPhase->setDefault(0.0f); | ||
| fKnobPhase->setCallback(this); | ||
|
|
||
| // knob Wave | ||
| fKnobWave = new ImageKnob(this, knobImage, ImageKnob::Vertical, WobbleJuicePlugin::paramWave); | ||
| fKnobWave->setAbsolutePos(77, 74); | ||
| fKnobWave->setRotationAngle(270); | ||
| fKnobWave->setRange(1.0f, 4.0f); | ||
| fKnobWave->setDefault(2.0f); | ||
| fKnobWave->setCallback(this); | ||
|
|
||
| // knob Drive | ||
| fKnobDrive = new ImageKnob(this, knobImage, ImageKnob::Vertical, WobbleJuicePlugin::paramDrive); | ||
| fKnobDrive->setAbsolutePos(362, 199); | ||
| fKnobDrive->setRotationAngle(270); | ||
| fKnobDrive->setRange(0.0f, 1.0f); | ||
| fKnobDrive->setDefault(0.5f); | ||
| fKnobDrive->setCallback(this); | ||
|
|
||
| // about button | ||
| Image aboutImageNormal(WobbleJuiceArtwork::aboutButtonNormalData, WobbleJuiceArtwork::aboutButtonNormalWidth, WobbleJuiceArtwork::aboutButtonNormalHeight); | ||
| Image aboutImageHover(WobbleJuiceArtwork::aboutButtonHoverData, WobbleJuiceArtwork::aboutButtonHoverWidth, WobbleJuiceArtwork::aboutButtonHoverHeight); | ||
| fButtonAbout = new ImageButton(this, aboutImageNormal, aboutImageHover, aboutImageHover); | ||
| fButtonAbout->setAbsolutePos(390, 20); | ||
| fButtonAbout->setCallback(this); | ||
|
|
||
| // set default values | ||
| d_programChanged(0); | ||
| } | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
| // DSP Callbacks | ||
|
|
||
| void WobbleJuiceUI::d_parameterChanged(uint32_t index, float value) | ||
| { | ||
| switch (index) | ||
| { | ||
| case WobbleJuicePlugin::paramDivision: | ||
| fKnobDivision->setValue(value); | ||
| break; | ||
| case WobbleJuicePlugin::paramReso: | ||
| fKnobResonance->setValue(value); | ||
| break; | ||
| case WobbleJuicePlugin::paramRange: | ||
| fKnobRange->setValue(value); | ||
| break; | ||
| case WobbleJuicePlugin::paramPhase: | ||
| fKnobPhase->setValue(value); | ||
| break; | ||
| case WobbleJuicePlugin::paramWave: | ||
| fKnobWave->setValue(value); | ||
| break; | ||
| case WobbleJuicePlugin::paramDrive: | ||
| fKnobDrive->setValue(value); | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| void WobbleJuiceUI::d_programChanged(uint32_t index) | ||
| { | ||
| if (index != 0) | ||
| return; | ||
|
|
||
| // Default values | ||
| fKnobDivision->setValue(4.0f); | ||
| fKnobResonance->setValue(0.1f); | ||
| fKnobRange->setValue(16000.0f); | ||
| fKnobPhase->setValue(0.0f); | ||
| fKnobWave->setValue(2.0f); | ||
| fKnobDrive->setValue(0.5f); | ||
| } | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
| // Widget Callbacks | ||
|
|
||
| void WobbleJuiceUI::imageButtonClicked(ImageButton* button, int) | ||
| { | ||
| if (button != fButtonAbout) | ||
| return; | ||
|
|
||
| fAboutWindow.exec(); | ||
| } | ||
|
|
||
| void WobbleJuiceUI::imageKnobDragStarted(ImageKnob* knob) | ||
| { | ||
| d_editParameter(knob->getId(), true); | ||
| } | ||
|
|
||
| void WobbleJuiceUI::imageKnobDragFinished(ImageKnob* knob) | ||
| { | ||
| d_editParameter(knob->getId(), false); | ||
| } | ||
|
|
||
| void WobbleJuiceUI::imageKnobValueChanged(ImageKnob* knob, float value) | ||
| { | ||
| d_setParameterValue(knob->getId(), value); | ||
| } | ||
|
|
||
| void WobbleJuiceUI::onDisplay() | ||
| { | ||
| fImgBackground.draw(); | ||
| } | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
|
|
||
| UI* createUI() | ||
| { | ||
| return new WobbleJuiceUI(); | ||
| } | ||
|
|
||
| // ----------------------------------------------------------------------- | ||
|
|
||
| END_NAMESPACE_DISTRHO |