diff --git a/AS.JPG b/AS.JPG
index 96bad46..6d2b1b4 100644
Binary files a/AS.JPG and b/AS.JPG differ
diff --git a/LICENSE.txt b/LICENSE.txt
index d582ae1..1515e57 100755
--- a/LICENSE.txt
+++ b/LICENSE.txt
@@ -1,8 +1,8 @@
-### AS###
+### AS ###
AS Logo/Monogram Copyright (c) 2017 Alfredo Santamaria , All rights reserved.
-Panel graphics in res/ are © 2017
+Panel graphics in res/ are (c) 2017
Derivative works may not use the AS logo or panel graphics including custom component graphics (knobs, switches, screws, caps,etc.).
@@ -40,7 +40,7 @@ The above copyright notice and this permission notice shall be included in all c
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-### HetrickCV ###
+### Waveshaper code by HetrickCV ###
Creative Commons Legal Code
@@ -165,7 +165,7 @@ express Statement of Purpose.
this CC0 or use of the Work.
-### Mental ###
+### Portions of code from Mental ###
Copyright (c) 2017 Strum strum@softhome.net , All rights reserved.
@@ -179,7 +179,7 @@ Redistribution and use in source and binary forms, with or without modification,
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-### Autodafe ###
+### seq-16, 8ch mixer and phaser portions of code from Autodafe ###
Copyright (c) 2016 Antonio Grazioli (AUtodafe) is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
@@ -187,7 +187,7 @@ The above copyright notice and this permission notice shall be included in all c
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-### martin-lueders/ML_modules ###
+### Portions of code from martin-lueders/ML_modules ###
BSD 3-Clause License
@@ -285,4 +285,36 @@ Dreampoint Design and Engineering
http://www.dreampoint.co.uk
-//ends
\ No newline at end of file
+//ends
+
+
+
+### BPM detect portions of code by Tomasz Sosnowski - KoralFX
+
+Copyright (c) 2018, Tomasz Sosnowski - KoralFX
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+* Neither the name of the copyright holder nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git a/Makefile b/Makefile
index ab3ff27..c8f351f 100755
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
RACK_DIR ?= ../..
SLUG = AS
-VERSION = 0.6.4
+VERSION = 0.6.5
FLAGS +=
SOURCES += $(wildcard src/*.cpp freeverb/*.cpp)
diff --git a/README.md b/README.md
index 6107404..0ee1b5c 100755
--- a/README.md
+++ b/README.md
@@ -44,11 +44,15 @@ V 0.6.1: Now BPM Clock outputs a short length trigger signal, as most of the ava
V 0.6.2: Small fix on the reset signal length.
+V 0.6.5: Added a Regular/Extended switch to change the clock from 40-250 to 30-300 range. Had to add the switch instead of simply changing the default settings to avoid changing the bpm tempo on the patches already using the clock.
+
### BPM to delay/hz calculator
A BPM to delay/hz calculator to setup easier those nice delay effects.
V 0.6.4: First relase of this module.
+V 0.6.5: Added an external input to detect a BPM from a LFO or some other sources, BPM detection code based on Koralfx Beatovnik from Tomek Sosnowski, nice work Tomek!.
+
### 8 Channel Mixer
Fundamental/Autodafe mixer module. Mods: graphics, sliders for channel volume, stereo or mono output(L channel outputs L+R signal if R channel is not active). Now with main mix mute button. Beware,the default setting for each channel volume is at 70% in stead of 0%.
@@ -134,16 +138,22 @@ Delay the start of a flow of signals by a set number of clock ticks (TAOS reques
V 0.5.5: First relase of this module.
+V 0.6.5: Now it features soft mute, so you can use it both for audio and cv signals without any switching noise.
+
### Kill Gate
Cut the flow of signals after a set number of clock ticks (TAOS request).
V 0.5.6: First relase of this module.
+V 0.6.5: Now it features soft mute, so you can use it both for audio and cv signals without any switching noise.
+
### Flow
Cut the flow of signals with a switch or a cv signal (TAOS request).
V 0.6.0: First relase of this module.
+V 0.6.5: Now it features soft mute, so you can use it both for audio and cv signals without any switching noise.
+
### Signal Delay
Delay the incomming CV signal by set milliseconds, with signal thru and delayed output. You can chain several Signal Delay modules together for unlimited length of delays. (TAOS request).
@@ -158,6 +168,8 @@ V 0.5.5 CHanged the time knob reading from exponential to linear, now you can se
V 0.6.3: bypass CV input added.
+V 0.6.5: Now it features soft bypass to avoid switching noise.
+
### Phaser
Autodafe's Phaser Fx module. Mods: graphics, bypass switch.
@@ -165,6 +177,8 @@ V 0.5.4: Added CV inputs for each parameter, updated look.
V 0.6.3: bypass CV input added.
+V 0.6.5: Now it features soft bypass to avoid switching noise.
+
### SuperDrive
Overdrive/clipping Fx module with DRIVE, TONE and GAIN parameters, to get those acid bass lines we all love!.
@@ -172,6 +186,8 @@ V 0.5.4: First relase of this module.
V 0.6.3: bypass CV input added.
+V 0.6.5: Now it features soft bypass to avoid switching noise(Results may change according to signal levels).
+
### Reverb
Reverb Fx module based on ML_modules reverb and Freeverb code, with DECAY, DAMP and BLEND parameters, a little bit tamed Reverb with mixed output signal.
@@ -179,6 +195,8 @@ Reverb Fx module based on ML_modules reverb and Freeverb code, with DECAY, DAMP
V 0.6.3: bypass CV input added.
+V 0.6.5: Now it features soft bypass to avoid switching noise.
+
### Tremolo
Tremolo Fx module with SHAPE, SPEED and BLEND parameters, and a phase switch (set your effect, duplicate the module and invert the phase for stereo tremolo setup)your Tremolo to go!.
@@ -186,6 +204,8 @@ Tremolo Fx module with SHAPE, SPEED and BLEND parameters, and a phase switch (se
V 0.6.3: bypass CV input added.
+V 0.6.5: Now it features soft bypass to avoid switching noise.
+
### WaveShaper
HetrickCV Wave Shaper module. Mods: graphics, bypass switch.
@@ -195,6 +215,8 @@ V 0.5.4: Updated look.
V 0.6.3: bypass CV input added.
+V 0.6.5: Now it features soft bypass to avoid switching noise.
+
### Blank Panel
Blank panels in 4, 6 & 8 HP.
diff --git a/res/BPMCalc.svg b/res/BPMCalc.svg
index bc1bc09..3771661 100644
--- a/res/BPMCalc.svg
+++ b/res/BPMCalc.svg
@@ -35,11 +35,11 @@
inkscape:window-height="1152"
id="namedview57"
showgrid="false"
- inkscape:zoom="2.1291543"
- inkscape:cx="120.30274"
- inkscape:cy="172.748"
- inkscape:window-x="358"
- inkscape:window-y="152"
+ inkscape:zoom="2.5657895"
+ inkscape:cx="33.287179"
+ inkscape:cy="190"
+ inkscape:window-x="0"
+ inkscape:window-y="0"
inkscape:window-maximized="0"
inkscape:current-layer="svg4541" />
\ No newline at end of file
+ inkscape:connector-curvature="0" />
\ No newline at end of file
diff --git a/res/BPMClock.svg b/res/BPMClock.svg
index 1ac17d5..4cf94a4 100644
--- a/res/BPMClock.svg
+++ b/res/BPMClock.svg
@@ -25,17 +25,17 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="4.0332085"
- inkscape:cx="19.015446"
- inkscape:cy="279.61115"
+ inkscape:zoom="5.9792362"
+ inkscape:cx="50.95199"
+ inkscape:cy="316.24946"
inkscape:document-units="mm"
inkscape:current-layer="layer3"
showgrid="true"
units="px"
- inkscape:window-width="1894"
- inkscape:window-height="1338"
- inkscape:window-x="-123"
- inkscape:window-y="19"
+ inkscape:window-width="1318"
+ inkscape:window-height="1351"
+ inkscape:window-x="178"
+ inkscape:window-y="0"
inkscape:window-maximized="0">
+ transform="matrix(0.14877078,0,0,0.14877078,-30.958201,-5.5737438)">
+
+
+
+
+
+
diff --git a/src/AS.hpp b/src/AS.hpp
index 15ff5f3..01c98d4 100755
--- a/src/AS.hpp
+++ b/src/AS.hpp
@@ -147,6 +147,13 @@ template
}
};
+ template
+ struct DisplayLedLight : BASE {
+ DisplayLedLight() {
+ this->box.size = mm2px(Vec(2.0, 2.0));
+ this->bgColor = nvgRGB(0x14, 0x14, 0x14);
+ }
+ };
struct OrangeLight : GrayModuleLightWidget {
OrangeLight() {
addBaseColor(COLOR_ORANGE);
diff --git a/src/BPMCalc.cpp b/src/BPMCalc.cpp
index 5549301..c82c9ab 100755
--- a/src/BPMCalc.cpp
+++ b/src/BPMCalc.cpp
@@ -1,31 +1,52 @@
//**************************************************************************************
//
//BPM Calculator module for VCV Rack by Alfredo Santamaria - AS - https://github.com/AScustomWorks/AS
-//
+//### BPM detect portions of code by Tomasz Sosnowski - KoralFX
//**************************************************************************************
#include "AS.hpp"
+#include "dsp/digital.hpp"
+
#include
#include
struct BPMCalc : Module {
enum ParamIds {
- TEMPO_PARAM,
+ TEMPO_PARAM,
NUM_PARAMS
};
- enum InputIds {
+ enum InputIds {
+ CLOCK_INPUT,
NUM_INPUTS
};
enum OutputIds {
NUM_OUTPUTS
};
enum LightIds {
+ CLOCK_LOCK_LIGHT,
+ CLOCK_LIGHT,
NUM_LIGHTS
};
+ //bpm detector variables
+ bool inMemory = false;
+ bool beatLock = false;
+ float beatTime = 0.0f;
+ int beatCount = 0;
+ int beatCountMemory = 0;
+ float beatOld = 0.0f;
+
+ std::string tempo = "---";
+
+ SchmittTrigger clockTrigger;
+ PulseGenerator LightPulse;
+ bool pulse = false;
+
+ //calculator variables
float bpm = 120;
+ float last_bpm = 0;
float millisecs = 60000;
float mult = 1000;
float millisecondsPerBeat;
@@ -75,92 +96,204 @@ struct BPMCalc : Module {
float trth_hz_d = 1.0f;
float trth_hz = 1.0f;
float trth_hz_t = 1.0f;
-
- BPMCalc() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
- void step() override;
+ void calculateValues(float bpm){
-};
+ millisecondsPerBeat = millisecs/bpm;
+ millisecondsPerMeasure = millisecondsPerBeat * 4;
-void BPMCalc::step() {
- bpm = params[TEMPO_PARAM].value;
- if (bpm<30){
- bpm = 30;
+ secondsPerBeat = 60 / bpm;
+ secondsPerMeasure = secondsPerBeat * 4;
+
+ bar = (millisecondsPerMeasure);
+
+ half_note_d = ( millisecondsPerBeat * 3 );
+ half_note = ( millisecondsPerBeat * 2 );
+ half_note_t = ( millisecondsPerBeat * 2 * 2 / 3 );
+
+ qt_note_d = ( millisecondsPerBeat / 2 ) * 3;
+ qt_note = millisecondsPerBeat;
+ qt_note_t = ( millisecondsPerBeat * 2 ) / 3;
+
+ eight_note_d = ( millisecondsPerBeat / 4 ) * 3;
+ eight_note = millisecondsPerBeat / 2;
+ eight_note_t = millisecondsPerBeat / 3;
+
+ sixth_note_d = ( millisecondsPerBeat / 4 ) * 1.5;
+ sixth_note = millisecondsPerBeat / 4;
+ sixth_note_t = millisecondsPerBeat / 6;
+
+ trth_note_d = ( millisecondsPerBeat / 8 ) * 1.5;
+ trth_note = millisecondsPerBeat / 8;
+ trth_note_t = millisecondsPerBeat / 8 * 2 / 3;
+ //hz measures
+ hz_bar = (1/secondsPerMeasure);
+
+ half_hz_d = mult / half_note_d;
+ half_hz = mult / half_note;
+ half_hz_t = mult / half_note_t;
+
+ qt_hz_d = mult / qt_note_d;
+ qt_hz = mult / qt_note;
+ qt_hz_t = mult / qt_note_t;
+
+ eight_hz_d = mult / eight_note_d;
+ eight_hz = mult / eight_note;
+ eight_hz_t = mult / eight_note_t;
+
+ sixth_hz_d = mult / sixth_note_d;
+ sixth_hz = mult / sixth_note;
+ sixth_hz_t = mult / sixth_note_t;
+
+ trth_hz_d = mult / trth_note_d;
+ trth_hz = mult / trth_note;
+ trth_hz_t = mult / trth_note_t;
+
+ last_bpm = bpm;
+ //seems like round calcs are not really needed:
+ /*
+ half_note_d = std::round(millisecondsPerBeat * 3 * mult)/mult;
+ half_note = std::round(millisecondsPerBeat * 2 * mult)/mult;
+ half_note_t = std::round(millisecondsPerBeat * 2 * 2 / 3 * mult)/mult;
+ */
}
- bpm = std::round(bpm);
- millisecondsPerBeat = millisecs/bpm;
- millisecondsPerMeasure = millisecondsPerBeat * 4;
- secondsPerBeat = 60 / bpm;
- secondsPerMeasure = secondsPerBeat * 4;
+ void refreshDetector() {
+
+ inMemory = false;
+ beatLock = false;
+ beatTime = 0.0f;
+ beatCount = 0;
+ beatCountMemory = 0;
+ beatOld = 0.0f;
+ tempo = "---";
+ pulse = false;
+
+ }
+
+
+ BPMCalc() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
+
+ void step() override;
+
+ void onReset() override {
- bar = (millisecondsPerMeasure);
+ refreshDetector();
- half_note_d = ( millisecondsPerBeat * 3 );
- half_note = ( millisecondsPerBeat * 2 );
- half_note_t = ( millisecondsPerBeat * 2 * 2 / 3 );
+ }
- qt_note_d = ( millisecondsPerBeat / 2 ) * 3;
- qt_note = millisecondsPerBeat;
- qt_note_t = ( millisecondsPerBeat * 2 ) / 3;
+ void onInitialize() {
- eight_note_d = ( millisecondsPerBeat / 4 ) * 3;
- eight_note = millisecondsPerBeat / 2;
- eight_note_t = millisecondsPerBeat / 3;
+ refreshDetector();
- sixth_note_d = ( millisecondsPerBeat / 4 ) * 1.5;
- sixth_note = millisecondsPerBeat / 4;
- sixth_note_t = millisecondsPerBeat / 6;
+ }
- trth_note_d = ( millisecondsPerBeat / 8 ) * 1.5;
- trth_note = millisecondsPerBeat / 8;
- trth_note_t = millisecondsPerBeat / 8 * 2 / 3;
- //hz measures
- hz_bar = (1/secondsPerMeasure);
+};
- half_hz_d = mult / half_note_d;
- half_hz = mult / half_note;
- half_hz_t = mult / half_note_t;
+void BPMCalc::step() {
- qt_hz_d = mult / qt_note_d;
- qt_hz = mult / qt_note;
- qt_hz_t = mult / qt_note_t;
+ //BPM detection code
+ float deltaTime = engineGetSampleTime();
+
+ if ( inputs[CLOCK_INPUT].active ) {
+
+ float clockInput = inputs[CLOCK_INPUT].value;
+ //A rising slope
+ if ( ( clockTrigger.process( inputs[CLOCK_INPUT].value ) ) && !inMemory ) {
+ beatCount++;
+ if(!beatLock){
+ lights[CLOCK_LIGHT].value = 1.0f;
+ LightPulse.trigger( 0.1f );
+ }
+ inMemory = true;
+
+ //BPM is locked
+ if ( beatCount == 2 ) {
+ lights[CLOCK_LOCK_LIGHT].value = 1.0f;
+ beatLock = true;
+ beatOld = beatTime;
+ }
+ //BPM is lost
+ if ( beatCount > 2 ) {
+
+ if ( fabs( beatOld - beatTime ) > 0.0005f ) {
+ beatLock = false;
+ beatCount = 0;
+ lights[CLOCK_LOCK_LIGHT].value = 0.0f;
+ tempo = "---";
+ }
+
+ }
+
+ beatTime = 0;
- eight_hz_d = mult / eight_note_d;
- eight_hz = mult / eight_note;
- eight_hz_t = mult / eight_note_t;
+ }
- sixth_hz_d = mult / sixth_note_d;
- sixth_hz = mult / sixth_note;
- sixth_hz_t = mult / sixth_note_t;
+ //Falling slope
+ if ( clockInput <= 0 && inMemory ) {
+ inMemory = false;
+ }
+ //When BPM is locked
+ if ( beatLock ) {
+ bpm = (int)round( 60 / beatOld );
+ tempo = std::to_string( (int)round(bpm) );
+ if(bpm!=last_bpm){
+ if(bpm<999){
+ calculateValues(bpm);
+ }else{
+ tempo = "OOR";
+ }
+ }
+
+ } //end of beatLock routine
+
+ beatTime += deltaTime;
+
+ //when beat is lost
+ if ( beatTime > 2 ) {
+ beatLock = false;
+ beatCount = 0;
+ lights[CLOCK_LOCK_LIGHT].value = 0.0f;
+ tempo = "---";
+ }
+ beatCountMemory = beatCount;
+
+ } else {
+ beatLock = false;
+ beatCount = 0;
+ //tempo = "OFF";
+ lights[CLOCK_LOCK_LIGHT].value = 0.0f;
+ //caluculate with knob value instead of bmp detector value
+ bpm = params[TEMPO_PARAM].value;
+ if (bpm<30){
+ bpm = 30;
+ }
+ bpm = (int)round(bpm);
+ tempo = std::to_string( (int)round(bpm) );
+ if(bpm!=last_bpm){
+ calculateValues(bpm);
+ }
- trth_hz_d = mult / trth_note_d;
- trth_hz = mult / trth_note;
- trth_hz_t = mult / trth_note_t;
+ }
+ pulse = LightPulse.process( 1.0 / engineGetSampleRate() );
+ lights[CLOCK_LIGHT].value = (pulse ? 1.0f : 0.0f);
- //seems like round calcs are not really needed:
- /*
- half_note_d = std::round(millisecondsPerBeat * 3 * mult)/mult;
- half_note = std::round(millisecondsPerBeat * 2 * mult)/mult;
- half_note_t = std::round(millisecondsPerBeat * 2 * 2 / 3 * mult)/mult;
- */
}
////////////////////////////////////
-struct BpmDisplayWidget : TransparentWidget {
- float *value;
+struct TempodisplayWidget : TransparentWidget {
+ std::string *value;
std::shared_ptr font;
- BpmDisplayWidget() {
+ TempodisplayWidget() {
font = Font::load(assetPlugin(plugin, "res/Segment7Standard.ttf"));
};
void draw(NVGcontext *vg) override
{
// Background
- //NVGcolor backgroundColor = nvgRGB(0x20, 0x20, 0x20);
NVGcolor backgroundColor = nvgRGB(0x20, 0x10, 0x10);
NVGcolor borderColor = nvgRGB(0x10, 0x10, 0x10);
nvgBeginPath(vg);
@@ -178,15 +311,15 @@ struct BpmDisplayWidget : TransparentWidget {
std::stringstream to_display;
to_display << std::setw(3) << *value;
- Vec textPos = Vec(4.0f, 17.0f);
+ Vec textPos = Vec(14.0f, 17.0f);
NVGcolor textColor = nvgRGB(0xdf, 0xd2, 0x2c);
nvgFillColor(vg, nvgTransRGBA(textColor, 16));
- nvgText(vg, textPos.x, textPos.y, "~~", NULL);
+ nvgText(vg, textPos.x, textPos.y, "~~~", NULL);
textColor = nvgRGB(0xda, 0xe9, 0x29);
nvgFillColor(vg, nvgTransRGBA(textColor, 16));
- nvgText(vg, textPos.x, textPos.y, "\\\\", NULL);
+ nvgText(vg, textPos.x, textPos.y, "\\\\\\", NULL);
textColor = nvgRGB(0xf0, 0x00, 0x00);
nvgFillColor(vg, textColor);
@@ -416,16 +549,22 @@ BPMCalcWidget::BPMCalcWidget(BPMCalc *module) : ModuleWidget(module) {
addChild(Widget::create(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
addChild(Widget::create(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
addChild(Widget::create(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
+
+ //BPM DETECTOR PORT
+ addInput(Port::create(Vec(20, 52), Port::INPUT, module, BPMCalc::CLOCK_INPUT));
+
//BPM DISPLAY
- BpmDisplayWidget *display = new BpmDisplayWidget();
- display->box.pos = Vec(43,54);
- display->box.size = Vec(45, 20);
- display->value = &module->bpm;
- addChild(display);
- //TEMPO KNOB
- addParam(ParamWidget::create(Vec(130, 45), module, BPMCalc::TEMPO_PARAM, 30.0f, 300.0f, 120.0f));
-
- //LABEL DISPLAY
+ TempodisplayWidget *display = new TempodisplayWidget();
+ display->box.pos = Vec(73,54);
+ display->box.size = Vec(55, 20);
+ display->value = &module->tempo;
+ addChild(display);
+ //DETECTOR LEDS
+ addChild(ModuleLightWidget::create>(Vec(77, 56), module, BPMCalc::CLOCK_LOCK_LIGHT));
+ addChild(ModuleLightWidget::create>(Vec(77, 66), module, BPMCalc::CLOCK_LIGHT));
+ //TEMPO KNOB
+ addParam(ParamWidget::create(Vec(156, 45), module, BPMCalc::TEMPO_PARAM, 30.0f, 300.0f, 120.0f));
+ //CALCULATOR DISPLAY
TxtDisplay *display1 = new TxtDisplay();
display1->module = module;
display1->box.pos = Vec(7, 120);
diff --git a/src/BPMClock.cpp b/src/BPMClock.cpp
index 4d7dd3a..852ba81 100755
--- a/src/BPMClock.cpp
+++ b/src/BPMClock.cpp
@@ -33,7 +33,8 @@ struct LFOGenerator {
struct BPMClock : Module {
enum ParamIds {
- TEMPO_PARAM,
+ TEMPO_PARAM,
+ MODE_PARAM,
TIMESIGTOP_PARAM,
TIMESIGBOTTOM_PARAM,
RESET_SWITCH,
@@ -66,6 +67,7 @@ struct BPMClock : Module {
SchmittTrigger run_button_trig;
SchmittTrigger reset_btn_trig;
SchmittTrigger reset_ext_trig;
+ SchmittTrigger bpm_mode_trig;
PulseGenerator resetPulse;
bool reset_pulse = false;
@@ -129,8 +131,16 @@ void BPMClock::step() {
}
lights[RUN_LED].value = running ? 1.0f : 0.0f;
-
- tempo = std::round(params[TEMPO_PARAM].value);
+
+ if (params[MODE_PARAM].value){
+ //regular 40 to 250 bpm mode
+ tempo = std::round(params[TEMPO_PARAM].value);
+ }else{
+ //extended 30 to 300 mode
+ tempo = std::round(rescale(params[TEMPO_PARAM].value,40.0f,250.0f, 30.0f, 300.0f) );
+ }
+ //tempo = std::round(params[TEMPO_PARAM].value);
+
time_sig_top = std::round(params[TIMESIGTOP_PARAM].value);
time_sig_bottom = std::round(params[TIMESIGBOTTOM_PARAM].value);
time_sig_bottom = std::pow(2,time_sig_bottom+1);
@@ -283,11 +293,11 @@ struct BpmDisplayWidget : TransparentWidget {
NVGcolor textColor = nvgRGB(0xdf, 0xd2, 0x2c);
nvgFillColor(vg, nvgTransRGBA(textColor, 16));
- nvgText(vg, textPos.x, textPos.y, "~~", NULL);
+ nvgText(vg, textPos.x, textPos.y, "~~~", NULL);
textColor = nvgRGB(0xda, 0xe9, 0x29);
nvgFillColor(vg, nvgTransRGBA(textColor, 16));
- nvgText(vg, textPos.x, textPos.y, "\\\\", NULL);
+ nvgText(vg, textPos.x, textPos.y, "\\\\\\", NULL);
textColor = nvgRGB(0xf0, 0x00, 0x00);
nvgFillColor(vg, textColor);
@@ -327,7 +337,7 @@ struct SigDisplayWidget : TransparentWidget {
std::stringstream to_display;
to_display << std::setw(2) << *value;
- Vec textPos = Vec(3, 17);
+ Vec textPos = Vec(3.0f, 17.0f);
NVGcolor textColor = nvgRGB(0xdf, 0xd2, 0x2c);
nvgFillColor(vg, nvgTransRGBA(textColor, 16));
@@ -359,12 +369,14 @@ BPMClockWidget::BPMClockWidget(BPMClock *module) : ModuleWidget(module) {
addChild(Widget::create(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
//BPM DISPLAY
BpmDisplayWidget *display = new BpmDisplayWidget();
- display->box.pos = Vec(23,50);
+ display->box.pos = Vec(23,45);
display->box.size = Vec(45, 20);
display->value = &module->tempo;
addChild(display);
//TEMPO KNOB
- addParam(ParamWidget::create(Vec(26, 74), module, BPMClock::TEMPO_PARAM, 40.0f, 250.0f, 120.0f));
+ addParam(ParamWidget::create(Vec(8, 69), module, BPMClock::TEMPO_PARAM, 40.0f, 250.0f, 120.0f));
+ //OLD/NEW SWITCH FROM 40-250 TO 30-300
+ addParam(ParamWidget::create(Vec(67, 77), module, BPMClock::MODE_PARAM, 0.0f, 1.0f, 1.0f));
//SIG TOP DISPLAY
SigDisplayWidget *display2 = new SigDisplayWidget();
display2->box.pos = Vec(54,123);
diff --git a/src/DelayPlus.cpp b/src/DelayPlus.cpp
index 405e5eb..13a237e 100755
--- a/src/DelayPlus.cpp
+++ b/src/DelayPlus.cpp
@@ -1,7 +1,7 @@
//**************************************************************************************
//Delay Plus module for VCV Rack by Alfredo Santamaria - AS - https://github.com/AScustomWorks/AS
//
-//Code taken from the Fundamentals plugins by Andrew Belt http://www.vcvrack.com
+//Code based on Fundamental plugins by Andrew Belt http://www.vcvrack.com
//**************************************************************************************
#include "AS.hpp"
@@ -60,6 +60,12 @@ struct DelayPlusFx : Module {
bool fx_bypass = false;
float lastWet = 0.0f;
+ float fade_in_fx = 0.0f;
+ float fade_in_dry = 0.0f;
+ float fade_out_fx = 1.0f;
+ float fade_out_dry = 1.0f;
+ const float fade_speed = 0.001f;
+
DelayPlusFx() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {
}
@@ -88,12 +94,20 @@ struct DelayPlusFx : Module {
}
+ void resetFades(){
+ fade_in_fx = 0.0f;
+ fade_in_dry = 0.0f;
+ fade_out_fx = 1.0f;
+ fade_out_dry = 1.0f;
+ }
+
};
void DelayPlusFx::step() {
if (bypass_button_trig.process(params[BYPASS_SWITCH].value) || bypass_cv_trig.process(inputs[BYPASS_CV_INPUT].value) ){
fx_bypass = !fx_bypass;
+ resetFades();
}
lights[BYPASS_LED].value = fx_bypass ? 1.0f : 0.0f;
@@ -166,10 +180,25 @@ void DelayPlusFx::step() {
out = crossfade(signal_input, wet, mix);
//check bypass switch status
if (fx_bypass){
- outputs[OUT_OUTPUT].value = signal_input;
- }else{
- //do the delay calculations
- outputs[OUT_OUTPUT].value = out;
+ fade_in_dry += fade_speed;
+ if ( fade_in_dry > 1.0f ) {
+ fade_in_dry = 1.0f;
+ }
+ fade_out_fx -= fade_speed;
+ if ( fade_out_fx < 0.0f ) {
+ fade_out_fx = 0.0f;
+ }
+ outputs[OUT_OUTPUT].value = ( signal_input * fade_in_dry ) + ( out * fade_out_fx );
+ }else{
+ fade_in_fx += fade_speed;
+ if ( fade_in_fx > 1.0f ) {
+ fade_in_fx = 1.0f;
+ }
+ fade_out_dry -= fade_speed;
+ if ( fade_out_dry < 0.0f ) {
+ fade_out_dry = 0.0f;
+ }
+ outputs[OUT_OUTPUT].value = ( signal_input * fade_out_dry ) + ( out * fade_in_fx );
}
}
diff --git a/src/Flow.cpp b/src/Flow.cpp
index 0727ab4..36e1bf8 100755
--- a/src/Flow.cpp
+++ b/src/Flow.cpp
@@ -40,6 +40,11 @@ struct Flow: Module {
bool on_1 = false;
bool on_2 = false;
+
+ float mute_fade1 =0.0f;
+ float mute_fade2 =0.0f;
+ const float fade_speed = 0.001f;
+
Flow() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
void step() override;
@@ -81,11 +86,14 @@ void Flow::step() {
if (extReset1.process(inputs[RESET_1].value)) {
on_1 = false;
}
- if(on_1){
- outputs[OUTPUT_1].value = inputs[INPUT_1].value;
- }else{
- outputs[OUTPUT_1].value = 0.0f;
+ //SOFT MUTE/UNMUTE
+ mute_fade1 -= on_1 ? fade_speed : -fade_speed;
+ if ( mute_fade1 < 0.0f ) {
+ mute_fade1 = 0.0f;
+ } else if ( mute_fade1 > 1.0f ) {
+ mute_fade1 = 1.0f;
}
+ outputs[OUTPUT_1].value = inputs[INPUT_1].value * mute_fade1;
lights[TRIGGER_LED_1].value = on_1 ? 1.0f : 0.0f;
//TRIGGER 2
if (btnTrigger2.process(params[SWITCH_2].value)||extTrigger2.process(inputs[CV_TRIG_INPUT_2].value)) {
@@ -94,14 +102,15 @@ void Flow::step() {
if (extReset2.process(inputs[RESET_2].value)) {
on_2 = false;
}
- if(on_2){
- outputs[OUTPUT_2].value = inputs[INPUT_2].value;
- }else{
- outputs[OUTPUT_2].value = 0.0f;
+ //SOFT MUTE/UNMUTE
+ mute_fade2 -= on_2 ? fade_speed : -fade_speed;
+ if ( mute_fade2 < 0.0f ) {
+ mute_fade2 = 0.0f;
+ } else if ( mute_fade2 > 1.0f ) {
+ mute_fade2 = 1.0f;
}
+ outputs[OUTPUT_2].value = inputs[INPUT_2].value * mute_fade2;
lights[TRIGGER_LED_2].value = on_2 ? 1.0f : 0.0f;
-
-
}
////////////////////////////////////
diff --git a/src/KillGate.cpp b/src/KillGate.cpp
index 6c6fb8f..7c431ef 100644
--- a/src/KillGate.cpp
+++ b/src/KillGate.cpp
@@ -59,6 +59,10 @@ struct KillGate : Module {
bool gate1_open= true;
bool gate2_open= true;
+ float mute_fade1 = 0.0f;
+ float mute_fade2 = 0.0f;
+ const float fade_speed = 0.001f;
+
KillGate() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {
}
@@ -69,8 +73,8 @@ struct KillGate : Module {
count1 = 0;
count_limit_2 = 1;
count_2 = 0;
- gate1_open= false;
- gate2_open= false;
+ gate1_open= true;
+ gate2_open= true;
}
@@ -87,71 +91,65 @@ void KillGate::step(){
bool reset1 = false;
bool reset_2 = false;
///////////// counter 1
- if (reset_trigger_1.process(params[RST_BUTTON1].value)){
+ if (reset_trigger_1.process(params[RST_BUTTON1].value) || reset_ext_trigger_1.process(inputs[RESET_IN_1].value) ){
reset1 = true;
count1 = 0;
gate1_open=true;
resetLight1 = 1.0;
}
- if (reset_ext_trigger_1.process(inputs[RESET_IN_1].value)){
- reset1 = true;
- count1 = 0;
- gate1_open = true;
- resetLight1 = 1.0;
-
- }
resetLight1 -= resetLight1 / lightLambda / engineGetSampleRate();
lights[RESET_LIGHT1].value = resetLight1;
- if (reset1 == false){
- if (clock_trigger_1.process(inputs[CLK_IN_1].value) && count1 <= count_limit1){
- if (gate1_open){
- count1++;
+ if ( reset1 == false ) {
+ if ( clock_trigger_1.process( inputs[CLK_IN_1].value ) && count1 <= count_limit1 ) {
+ if ( gate1_open ) {
+ count1++;
}
}
}
- if (count1 == count_limit1){
- gate1_open = false;
+ if ( count1 == count_limit1 ) {
+ gate1_open = false;
}
- if (!gate1_open){
- outputs[OUTPUT_1].value = 0.0f;
- }else{
- outputs[OUTPUT_1].value = inputs[INPUT_1].value;
+ //SOFT MUTE/UNMUTE
+ mute_fade1 -= !gate1_open ? fade_speed : -fade_speed;
+ if ( mute_fade1 < 0.0f ) {
+ mute_fade1 = 0.0f;
+ } else if ( mute_fade1 > 1.0f ) {
+ mute_fade1 = 1.0f;
}
+ outputs[OUTPUT_1].value = inputs[INPUT_1].value * mute_fade1;
+
///////////// counter 2
- if (reset_trigger_2.process(params[RST_BUTTON2].value)){
+ if ( reset_trigger_2.process( params[RST_BUTTON2].value ) || reset_ext_trigger_2.process( inputs[RESET_IN_2].value ) ) {
reset_2 = true;
count_2 = 0;
- gate2_open=true;
+ gate2_open = true;
resetLight2 = 1.0f;
}
- if (reset_ext_trigger_2.process(inputs[RESET_IN_2].value)){
- reset_2 = true;
- count_2 = 0;
- gate2_open=true;
- resetLight2 = 1.0f;
- }
+
resetLight2 -= resetLight2 / lightLambda / engineGetSampleRate();
lights[RESET_LIGHT2].value = resetLight2;
- if (reset_2 == false){
- if (clock_trigger_2.process(inputs[CLK_IN_2].value) && count_2 <= count_limit_2){
- if (gate2_open){
- count_2++;
+ if ( reset_2 == false ) {
+ if ( clock_trigger_2.process( inputs[CLK_IN_2].value ) && count_2 <= count_limit_2 ) {
+ if ( gate2_open ) {
+ count_2++;
}
}
}
- if (count_2 == count_limit_2){
- gate2_open = false;
+ if ( count_2 == count_limit_2 ) {
+ gate2_open = false;
}
- if (!gate2_open){
- outputs[OUTPUT_2].value = 0.0f;
- }else{
- outputs[OUTPUT_2].value = inputs[INPUT_2].value;
+ //SOFT MUTE/UNMUTE
+ mute_fade2 -= !gate2_open ? fade_speed : -fade_speed;
+ if ( mute_fade2 < 0.0f ) {
+ mute_fade2 = 0.0f;
+ } else if ( mute_fade2 > 1.0f ) {
+ mute_fade2 = 1.0f;
}
-
+ outputs[OUTPUT_2].value = inputs[INPUT_2].value * mute_fade2;
}
///////////////////////////////////
diff --git a/src/LaunchGate.cpp b/src/LaunchGate.cpp
index a5db239..76decb5 100644
--- a/src/LaunchGate.cpp
+++ b/src/LaunchGate.cpp
@@ -59,6 +59,10 @@ struct LaunchGate : Module {
bool gate1_open= false;
bool gate2_open= false;
+ float mute_fade1 = 0.0f;
+ float mute_fade2 = 0.0f;
+ const float fade_speed = 0.001f;
+
LaunchGate() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {
}
@@ -87,71 +91,63 @@ void LaunchGate::step(){
bool reset1 = false;
bool reset_2 = false;
///////////// counter 1
- if (reset_trigger_1.process(params[RST_BUTTON1].value)){
- reset1 = true;
- count1 = 0;
- gate1_open=false;
- resetLight1 = 1.0f;
-
+ if ( reset_trigger_1.process( params[RST_BUTTON1].value ) || reset_ext_trigger_1.process( inputs[RESET_IN_1].value ) ) {
+ reset1 = true;
+ count1 = 0;
+ gate1_open = false;
+ resetLight1 = 1.0f;
+ mute_fade1 = 0.0f;
}
- if (reset_ext_trigger_1.process(inputs[RESET_IN_1].value)){
- reset1 = true;
- count1 = 0;
- gate1_open = false;
- resetLight1 = 1.0f;
-
- }
resetLight1 -= resetLight1 / lightLambda / engineGetSampleRate();
lights[RESET_LIGHT1].value = resetLight1;
- if (reset1 == false){
- if (clock_trigger_1.process(inputs[CLK_IN_1].value) && count1 <= count_limit1){
- if (!gate1_open){
- count1++;
+ if ( reset1 == false ) {
+ if ( clock_trigger_1.process( inputs[CLK_IN_1].value ) && count1 <= count_limit1 ) {
+ if ( !gate1_open ) {
+ count1++;
}
}
}
- if (count1 == count_limit1){
- gate1_open = true;
+ if ( count1 == count_limit1 ) {
+ gate1_open = true;
}
- if (gate1_open){
- outputs[OUTPUT_1].value = inputs[INPUT_1].value;
- }else{
- outputs[OUTPUT_1].value = 0.0f;
+ //SOFT MUTE/UNMUTE
+ mute_fade1 += gate1_open ? fade_speed : -fade_speed;
+ if ( mute_fade1 < 0.0f ) {
+ mute_fade1 = 0.0f;
+ } else if ( mute_fade1 > 1.0f ) {
+ mute_fade1 = 1.0f;
}
+ outputs[OUTPUT_1].value = inputs[INPUT_1].value * mute_fade1;
///////////// counter 2
- if (reset_trigger_2.process(params[RST_BUTTON2].value)){
+ if ( reset_trigger_2.process( params[RST_BUTTON2].value ) || reset_ext_trigger_2.process( inputs[RESET_IN_2].value ) ) {
reset_2 = true;
count_2 = 0;
- gate2_open=false;
+ gate2_open = false;
resetLight2 = 1.0f;
}
- if (reset_ext_trigger_2.process(inputs[RESET_IN_2].value)){
- reset_2 = true;
- count_2 = 0;
- gate2_open=false;
- resetLight2 = 1.0f;
- }
resetLight2 -= resetLight2 / lightLambda / engineGetSampleRate();
lights[RESET_LIGHT2].value = resetLight2;
- if (reset_2 == false){
- if (clock_trigger_2.process(inputs[CLK_IN_2].value) && count_2 <= count_limit_2){
- if (!gate2_open){
- count_2++;
+ if ( reset_2 == false ) {
+ if ( clock_trigger_2.process( inputs[CLK_IN_2].value ) && count_2 <= count_limit_2 ) {
+ if ( !gate2_open ) {
+ count_2++;
}
}
}
- if (count_2 == count_limit_2){
- gate2_open = true;
+ if ( count_2 == count_limit_2 ) {
+ gate2_open = true;
}
- if (gate2_open){
- outputs[OUTPUT_2].value = inputs[INPUT_2].value;
- }else{
- outputs[OUTPUT_2].value = 0.0f;
+ //SOFT MUTE/UNMUTE
+ mute_fade2 += gate2_open ? fade_speed : -fade_speed;
+ if ( mute_fade2 < 0.0f ) {
+ mute_fade2 = 0.0f;
+ } else if ( mute_fade2 > 1.0f ) {
+ mute_fade2 = 1.0f;
}
-
+ outputs[OUTPUT_2].value = inputs[INPUT_2].value * mute_fade2;
}
///////////////////////////////////
diff --git a/src/Phaser.cpp b/src/Phaser.cpp
index b68dcf1..8ca6b1e 100644
--- a/src/Phaser.cpp
+++ b/src/Phaser.cpp
@@ -44,6 +44,13 @@ struct PhaserFx : Module{
SchmittTrigger bypass_cv_trig;
bool fx_bypass = false;
+
+ float fade_in_fx = 0.0f;
+ float fade_in_dry = 0.0f;
+ float fade_out_fx = 1.0f;
+ float fade_out_dry = 1.0f;
+ const float fade_speed = 0.001f;
+
PhaserFx() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
void step() override;
@@ -70,6 +77,13 @@ struct PhaserFx : Module{
}
+ void resetFades(){
+ fade_in_fx = 0.0f;
+ fade_in_dry = 0.0f;
+ fade_out_fx = 1.0f;
+ fade_out_dry = 1.0f;
+ }
+
};
#define SR (44100.f) //sample rate
@@ -165,7 +179,8 @@ Phaser *pha = new Phaser();
void PhaserFx::step() {
if (bypass_button_trig.process(params[BYPASS_SWITCH].value) || bypass_cv_trig.process(inputs[BYPASS_CV_INPUT].value) ){
- fx_bypass = !fx_bypass;
+ fx_bypass = !fx_bypass;
+ resetFades();
}
lights[BYPASS_LED].value = fx_bypass ? 1.00 : 0.0;
@@ -184,11 +199,34 @@ void PhaserFx::step() {
float out = pha->Update(input);
//check bypass switch status
+ /*
if (fx_bypass){
outputs[OUT].value = input * 5.0f;
}else{
outputs[OUT].value = out * 5.0f;
}
+*/
+ if (fx_bypass){
+ fade_in_dry += fade_speed;
+ if ( fade_in_dry > 1.0f ) {
+ fade_in_dry = 1.0f;
+ }
+ fade_out_fx -= fade_speed;
+ if ( fade_out_fx < 0.0f ) {
+ fade_out_fx = 0.0f;
+ }
+ outputs[OUT].value = ( (input * 5.0f) * fade_in_dry ) + ( (out*5.0f) * fade_out_fx );
+ }else{
+ fade_in_fx += fade_speed;
+ if ( fade_in_fx > 1.0f ) {
+ fade_in_fx = 1.0f;
+ }
+ fade_out_dry -= fade_speed;
+ if ( fade_out_dry < 0.0f ) {
+ fade_out_dry = 0.0f;
+ }
+ outputs[OUT].value = ( (input * 5.0f) * fade_out_dry ) + ( (out*5.0f) * fade_in_fx );
+ }
lights[RATE_LIGHT].value = clamp(params[RATE_PARAM].value + inputs[RATE_CV_INPUT].value / 10.0f, 0.0f, 1.0f);
lights[FBK_LIGHT].value = clamp(params[FBK_PARAM].value + inputs[FEEDBACK_CV_INPUT].value / 10.0f, 0.0f, 1.0f);
diff --git a/src/Reverb.cpp b/src/Reverb.cpp
index dad1bd7..a024eab 100755
--- a/src/Reverb.cpp
+++ b/src/Reverb.cpp
@@ -48,6 +48,12 @@ struct ReverbFx : Module{
bool fx_bypass = false;
+ float fade_in_fx = 0.0f;
+ float fade_in_dry = 0.0f;
+ float fade_out_fx = 1.0f;
+ float fade_out_dry = 1.0f;
+ const float fade_speed = 0.001f;
+
ReverbFx() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {
float gSampleRate = engineGetSampleRate();
@@ -79,6 +85,13 @@ struct ReverbFx : Module{
fx_bypass = !!json_boolean_value(bypassJ);
}
+
+ void resetFades(){
+ fade_in_fx = 0.0f;
+ fade_in_dry = 0.0f;
+ fade_out_fx = 1.0f;
+ fade_out_dry = 1.0f;
+ }
};
@@ -98,6 +111,7 @@ void ReverbFx::step() {
if (bypass_button_trig.process(params[BYPASS_SWITCH].value) || bypass_cv_trig.process(inputs[BYPASS_CV_INPUT].value) ){
fx_bypass = !fx_bypass;
+ resetFades();
}
lights[BYPASS_LED].value = fx_bypass ? 1.0f : 0.0f;
@@ -118,12 +132,29 @@ void ReverbFx::step() {
reverb.process(input_signal, out1, out2);
+ float out = input_signal + out1 * clamp(params[BLEND_PARAM].value + inputs[BLEND_CV_INPUT].value / 10.0f, 0.0f, 1.0f);
+
//check bypass switch status
if (fx_bypass){
- outputs[SIGNAL_OUTPUT].value = inputs[SIGNAL_INPUT].value;
- }else {
- outputs[SIGNAL_OUTPUT].value = input_signal + out1 * clamp(params[BLEND_PARAM].value + inputs[BLEND_CV_INPUT].value / 10.0f, 0.0f, 1.0f);
- //outputs[SIGNAL_OUTPUT2].value = input_signal + out2 * clamp(params[BLEND_PARAM].value + inputs[BLEND_CV_INPUT].value / 10.0, 0.0, 1.0);
+ fade_in_dry += fade_speed;
+ if ( fade_in_dry > 1.0f ) {
+ fade_in_dry = 1.0f;
+ }
+ fade_out_fx -= fade_speed;
+ if ( fade_out_fx < 0.0f ) {
+ fade_out_fx = 0.0f;
+ }
+ outputs[SIGNAL_OUTPUT].value = ( input_signal * fade_in_dry ) + ( out * fade_out_fx );
+ }else{
+ fade_in_fx += fade_speed;
+ if ( fade_in_fx > 1.0f ) {
+ fade_in_fx = 1.0f;
+ }
+ fade_out_dry -= fade_speed;
+ if ( fade_out_dry < 0.0f ) {
+ fade_out_dry = 0.0f;
+ }
+ outputs[SIGNAL_OUTPUT].value = ( input_signal * fade_out_dry ) + ( out * fade_in_fx );
}
lights[DECAY_LIGHT].value = clamp(params[DECAY_PARAM].value + inputs[DECAY_CV_INPUT].value / 10.0f, 0.0f, 1.0f);
diff --git a/src/SuperDrive.cpp b/src/SuperDrive.cpp
index 4712cab..ece39b4 100644
--- a/src/SuperDrive.cpp
+++ b/src/SuperDrive.cpp
@@ -49,6 +49,13 @@ struct SuperDriveFx : Module{
RCFilter highpassFilter;
bool fx_bypass = false;
+
+ float fade_in_fx = 0.0f;
+ float fade_in_dry = 0.0f;
+ float fade_out_fx = 1.0f;
+ float fade_out_dry = 1.0f;
+ const float fade_speed = 0.001f;
+
SuperDriveFx() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
void step() override;
@@ -75,6 +82,13 @@ struct SuperDriveFx : Module{
}
+ void resetFades(){
+ fade_in_fx = 0.0f;
+ fade_in_dry = 0.0f;
+ fade_out_fx = 1.0f;
+ fade_out_dry = 1.0f;
+ }
+
float input_signal=0.0f;
float drive = 0.1f;
float process= 0.0f;
@@ -85,10 +99,10 @@ struct SuperDriveFx : Module{
void SuperDriveFx::step() {
- if (bypass_button_trig.process(params[BYPASS_SWITCH].value) || bypass_cv_trig.process(inputs[BYPASS_CV_INPUT].value) )
- {
+ if (bypass_button_trig.process(params[BYPASS_SWITCH].value) || bypass_cv_trig.process(inputs[BYPASS_CV_INPUT].value) ){
fx_bypass = !fx_bypass;
- }
+ resetFades();
+ }
lights[BYPASS_LED].value = fx_bypass ? 1.0f : 0.0f;
float input_signal = inputs[SIGNAL_INPUT].value;
@@ -117,13 +131,26 @@ void SuperDriveFx::step() {
//check bypass switch status
if (fx_bypass){
- outputs[SIGNAL_OUTPUT].value = inputs[SIGNAL_INPUT].value;
- }else {
- outputs[SIGNAL_OUTPUT].value = output_signal*3.5f;// 3.5;
+ fade_in_dry += fade_speed;
+ if ( fade_in_dry > 1.0f ) {
+ fade_in_dry = 1.0f;
+ }
+ fade_out_fx -= fade_speed;
+ if ( fade_out_fx < 0.0f ) {
+ fade_out_fx = 0.0f;
+ }
+ outputs[SIGNAL_OUTPUT].value = ( input_signal * fade_in_dry ) + ( (output_signal*3.5f) * fade_out_fx );
+ }else{
+ fade_in_fx += fade_speed;
+ if ( fade_in_fx > 1.0f ) {
+ fade_in_fx = 1.0f;
+ }
+ fade_out_dry -= fade_speed;
+ if ( fade_out_dry < 0.0f ) {
+ fade_out_dry = 0.0f;
+ }
+ outputs[SIGNAL_OUTPUT].value = ( input_signal * fade_out_dry ) + ( (output_signal*3.5f) * fade_in_fx );
}
- //lights without cv input - old
- //lights[DRIVE_LIGHT].value = params[DRIVE_PARAM].value;
- //lights[GAIN_LIGHT].value = params[OUTPUT_GAIN_PARAM].value;
lights[DRIVE_LIGHT].value = clamp(params[DRIVE_PARAM].value + inputs[DRIVE_CV_INPUT].value / 10.0f, 0.0f, 1.0f);
lights[TONE_LIGHT].value = clamp(params[TONE_PARAM].value + inputs[TONE_CV_INPUT].value / 10.0f, 0.0f, 1.0f);
diff --git a/src/Tremolo.cpp b/src/Tremolo.cpp
index c7492ed..ec61920 100644
--- a/src/Tremolo.cpp
+++ b/src/Tremolo.cpp
@@ -53,21 +53,6 @@ struct LowFrequencyOscillator {
else
return -1.0f + tri(invert ? phase - 0.25f : phase - 0.75f);
}
- /*
- float saw(float x) {
- return 2.0 * (x - roundf(x));
- }
- float saw() {
- if (offset)
- return invert ? 2.0 * (1.0 - phase) : 2.0 * phase;
- else
- return saw(phase) * (invert ? -1.0 : 1.0);
- }
- float sqr() {
- float sqr = (phase < pw) ^ invert ? 1.0 : -1.0;
- return offset ? sqr + 1.0 : sqr;
- }
- */
float light() {
return sinf(2.0f*M_PI * phase);
}
@@ -111,6 +96,12 @@ struct TremoloFx : Module{
bool fx_bypass = false;
+ float fade_in_fx = 0.0f;
+ float fade_in_dry = 0.0f;
+ float fade_out_fx = 1.0f;
+ float fade_out_dry = 1.0f;
+ const float fade_speed = 0.001f;
+
TremoloFx() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
void step() override;
@@ -137,7 +128,14 @@ struct TremoloFx : Module{
}
- float input_signal =0.0f;
+ void resetFades(){
+ fade_in_fx = 0.0f;
+ fade_in_dry = 0.0f;
+ fade_out_fx = 1.0f;
+ fade_out_dry = 1.0f;
+ }
+
+ float input_signal = 0.0f;
float output_signal = 0.0f;
float tremolo_signal = 0.0f;
float blend_control = 0.0f;
@@ -149,6 +147,7 @@ void TremoloFx::step() {
if (bypass_button_trig.process(params[BYPASS_SWITCH].value) || bypass_cv_trig.process(inputs[BYPASS_CV_INPUT].value) ){
fx_bypass = !fx_bypass;
+ resetFades();
}
lights[BYPASS_LED].value = fx_bypass ? 1.0f : 0.0f;
@@ -166,14 +165,31 @@ void TremoloFx::step() {
lfo_modulation = 5.0f * interp;
+ tremolo_signal = input_signal * clamp(lfo_modulation/10.0f, 0.0f, 1.0f);
+ blend_control = clamp(params[BLEND_PARAM].value + inputs[BLEND_CV_INPUT].value / 10.0f, 0.0f, 1.0f);
+ output_signal = crossfade(input_signal,tremolo_signal,blend_control);
+
//check bypass switch status
if (fx_bypass){
- outputs[SIGNAL_OUTPUT].value = input_signal;
- }else {
- tremolo_signal = input_signal * clamp(lfo_modulation/10.0f, 0.0f, 1.0f);
- blend_control = clamp(params[BLEND_PARAM].value + inputs[BLEND_CV_INPUT].value / 10.0f, 0.0f, 1.0f);
- output_signal = crossfade(input_signal,tremolo_signal,blend_control);
- outputs[SIGNAL_OUTPUT].value = output_signal;
+ fade_in_dry += fade_speed;
+ if ( fade_in_dry > 1.0f ) {
+ fade_in_dry = 1.0f;
+ }
+ fade_out_fx -= fade_speed;
+ if ( fade_out_fx < 0.0f ) {
+ fade_out_fx = 0.0f;
+ }
+ outputs[SIGNAL_OUTPUT].value = ( input_signal * fade_in_dry ) + ( output_signal * fade_out_fx );
+ }else{
+ fade_in_fx += fade_speed;
+ if ( fade_in_fx > 1.0f ) {
+ fade_in_fx = 1.0f;
+ }
+ fade_out_dry -= fade_speed;
+ if ( fade_out_dry < 0.0f ) {
+ fade_out_dry = 0.0f;
+ }
+ outputs[SIGNAL_OUTPUT].value = ( input_signal * fade_out_dry ) + ( output_signal * fade_in_fx );
}
lights[PHASE_POS_LIGHT].setBrightnessSmooth(fmaxf(0.0f, oscillator.light()));
diff --git a/src/WaveShaper.cpp b/src/WaveShaper.cpp
index a9c51f9..b7bb0bd 100755
--- a/src/WaveShaper.cpp
+++ b/src/WaveShaper.cpp
@@ -34,6 +34,12 @@ struct WaveShaper : Module {
SchmittTrigger bypass_cv_trig;
bool fx_bypass = false;
+ float fade_in_fx = 0.0f;
+ float fade_in_dry = 0.0f;
+ float fade_out_fx = 1.0f;
+ float fade_out_dry = 1.0f;
+ const float fade_speed = 0.001f;
+
WaveShaper() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
void step() override;
@@ -59,6 +65,13 @@ struct WaveShaper : Module {
}
+ void resetFades(){
+ fade_in_fx = 0.0f;
+ fade_in_dry = 0.0f;
+ fade_out_fx = 1.0f;
+ fade_out_dry = 1.0f;
+ }
+
};
@@ -66,6 +79,7 @@ void WaveShaper::step() {
if (bypass_button_trig.process(params[BYPASS_SWITCH].value) || bypass_cv_trig.process(inputs[BYPASS_CV_INPUT].value) ){
fx_bypass = !fx_bypass;
+ resetFades();
}
lights[BYPASS_LED].value = fx_bypass ? 1.0f : 0.0f;
@@ -87,10 +101,28 @@ void WaveShaper::step() {
output *= 10.0f;
//check for bypass switch status
if (fx_bypass){
- outputs[OUTPUT].value = inputs[INPUT].value;
- }else{
- outputs[OUTPUT].value = output;
- }
+ fade_in_dry += fade_speed;
+ if ( fade_in_dry > 1.0f ) {
+ fade_in_dry = 1.0f;
+ }
+ fade_out_fx -= fade_speed;
+ if ( fade_out_fx < 0.0f ) {
+ fade_out_fx = 0.0f;
+ }
+ outputs[OUTPUT].value = ( input * fade_in_dry ) + ( output * fade_out_fx );
+ }else{
+ fade_in_fx += fade_speed;
+ if ( fade_in_fx > 1.0f ) {
+ fade_in_fx = 1.0f;
+ }
+ fade_out_dry -= fade_speed;
+ if ( fade_out_dry < 0.0f ) {
+ fade_out_dry = 0.0f;
+ }
+ outputs[OUTPUT].value = ( input * fade_out_dry ) + ( output * fade_in_fx );
+ }
+
+
}
struct WaveShaperWidget : ModuleWidget