diff --git a/AS.JPG b/AS.JPG
index 722d607..e59d602 100644
Binary files a/AS.JPG and b/AS.JPG differ
diff --git a/Makefile b/Makefile
index 2c320e1..5360faa 100755
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
RACK_DIR ?= ../..
SLUG = AS
-VERSION = 0.6.9
+VERSION = 0.6.10
FLAGS +=
SOURCES += $(wildcard src/*.cpp freeverb/*.cpp)
diff --git a/README.md b/README.md
index b69c547..360ac30 100755
--- a/README.md
+++ b/README.md
@@ -96,11 +96,15 @@ V 0.5.5 Extendend the freq range 1 octave below.
V 0.5.7 Module size reduced to 4HP
+V 0.6.10 Added a base frequency switch to change from A (original and default) to C (to match the current VCV standard).
+
### TinySine
VCV tutorial module. Mods: graphics, proper sine wave.
V 0.5.7 Module size reduced to 4HP
+V 0.6.10 Added a base frequency switch to change from A (original and default) to C (to match the current VCV standard).
+
### TriLFO
Fundamental LFO module. Mods:graphics, controls stripped to the basics but you get 3 LFOS on the same space.
@@ -189,6 +193,11 @@ CV to Trigger module. Feed a midi signal to the CV inputs and it will output one
V 0.6.7: First relase of this module.
+### Zero Crossing CV 2 T
+Zero crossing CV to Trigger module. Each time a CV input hits 0v it will generate a trigger signal on the respective output. User request.
+
+V 0.6.10: First relase of this module.
+
### Delay Plus
Fundamental Delay module. Mods: graphics, digital display to show delay time in MS , wet signal send & return, bypass switch.
diff --git a/res/SawOSC.svg b/res/SawOSC.svg
index 64996fd..2a55b2c 100644
--- a/res/SawOSC.svg
+++ b/res/SawOSC.svg
@@ -25,20 +25,20 @@
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
- inkscape:zoom="3.1789474"
- inkscape:cx="40.066216"
- inkscape:cy="89.33775"
+ inkscape:zoom="2.2623377"
+ inkscape:cx="-17.5"
+ inkscape:cy="96.680827"
inkscape:document-units="mm"
- inkscape:current-layer="layer2"
+ inkscape:current-layer="layer1"
showgrid="false"
units="px"
inkscape:snap-bbox="true"
inkscape:snap-page="true"
inkscape:bbox-nodes="true"
inkscape:snap-bbox-edge-midpoints="true"
- inkscape:window-width="1004"
- inkscape:window-height="1393"
- inkscape:window-x="541"
+ inkscape:window-width="1419"
+ inkscape:window-height="1367"
+ inkscape:window-x="-86"
inkscape:window-y="0"
inkscape:window-maximized="0" />
+ inkscape:connector-curvature="0"
+ sodipodi:nodetypes="cc" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/SineOSC.svg b/res/SineOSC.svg
index a946d0c..abdf2fa 100644
--- a/res/SineOSC.svg
+++ b/res/SineOSC.svg
@@ -26,7 +26,7 @@
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="3.1789474"
- inkscape:cx="123.11257"
+ inkscape:cx="65.231776"
inkscape:cy="227.74834"
inkscape:document-units="mm"
inkscape:current-layer="layer1"
@@ -38,8 +38,8 @@
inkscape:snap-bbox-edge-midpoints="true"
inkscape:window-width="1943"
inkscape:window-height="1385"
- inkscape:window-x="272"
- inkscape:window-y="31"
+ inkscape:window-x="480"
+ inkscape:window-y="24"
inkscape:window-maximized="0" />
@@ -318,5 +318,73 @@
inkscape:connector-curvature="0" />
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/ZeroCV2T.svg b/res/ZeroCV2T.svg
new file mode 100644
index 0000000..9f92503
--- /dev/null
+++ b/res/ZeroCV2T.svg
@@ -0,0 +1,549 @@
+
+
+
+
diff --git a/src/AS.cpp b/src/AS.cpp
index a8dcf91..75703f7 100755
--- a/src/AS.cpp
+++ b/src/AS.cpp
@@ -34,6 +34,7 @@ void init(rack::Plugin *p) {
p->addModel(modelTriggersMKIII);
p->addModel(modelBPMCalc);
p->addModel(modelCv2T);
+ p->addModel(modelZeroCV2T);
p->addModel(modelReScale);
//EFFECTS
diff --git a/src/AS.hpp b/src/AS.hpp
index ab03c09..c14b731 100755
--- a/src/AS.hpp
+++ b/src/AS.hpp
@@ -36,6 +36,7 @@ extern Model *modelFlow;
extern Model *modelSignalDelay;
extern Model *modelBPMCalc;
extern Model *modelCv2T;
+extern Model *modelZeroCV2T;
extern Model *modelReScale;
extern Model *modelDelayPlusFx;
diff --git a/src/ReScale.cpp b/src/ReScale.cpp
index 4d4ff78..06fafea 100644
--- a/src/ReScale.cpp
+++ b/src/ReScale.cpp
@@ -131,4 +131,4 @@ ReScaleWidget::ReScaleWidget(ReScale *module) : ModuleWidget(module) {
}
-Model *modelReScale = Model::create("AS", "ReScale", "Voltage Converter", UTILITY_TAG);
\ No newline at end of file
+Model *modelReScale = Model::create("AS", "ReScale", "ReScale - Voltage Converter", UTILITY_TAG);
\ No newline at end of file
diff --git a/src/SawOSC.cpp b/src/SawOSC.cpp
index 1463fc8..740fa71 100755
--- a/src/SawOSC.cpp
+++ b/src/SawOSC.cpp
@@ -9,6 +9,7 @@
struct SawOsc : Module {
enum ParamIds {
PITCH_PARAM,
+ BASE_PARAM,
PW_PARAM,
NUM_PARAMS
};
@@ -28,6 +29,8 @@ struct SawOsc : Module {
float phase = 0.0f;
float blinkPhase = 0.0f;
+ float freq = 0.0f;
+ int base_freq = 0;
SawOsc() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
void step() override;
@@ -37,10 +40,18 @@ void SawOsc::step() {
// Implement a simple sine oscillator
float deltaTime = 1.0f / engineGetSampleRate();
// Compute the frequency from the pitch parameter and input
+ base_freq = params[BASE_PARAM].value;
float pitch = params[PITCH_PARAM].value;
pitch += inputs[PITCH_INPUT].value;
pitch = clamp(pitch, -4.0f, 4.0f);
- float freq = 440.0f * powf(2.0f, pitch);
+
+ if(base_freq==1){
+ //Note A4
+ freq = 440.0f * powf(2.0f, pitch);
+ }else{
+ // Note C4
+ freq = 261.626f * powf(2.0f, pitch);
+ }
// Accumulate the phase
phase += freq * deltaTime;
@@ -91,12 +102,17 @@ SawOscWidget::SawOscWidget(SawOsc *module) : ModuleWidget(module) {
//LIGHT
addChild(ModuleLightWidget::create>(Vec(22-15, 57), module, SawOsc::FREQ_LIGHT));
//PARAMS
- //addParam(ParamWidget::create(Vec(26, 60), module, SawOsc::PITCH_PARAM, -3.0, 3.0, 0.0));
- addParam(ParamWidget::create(Vec(26-15, 60), module, SawOsc::PITCH_PARAM, -4.0, 4.0, 0.0));
+ //addParam(ParamWidget::create(Vec(26, 60), module, SawOsc::PITCH_PARAM, -3.0f, 3.0f, 0.0f));
+ addParam(ParamWidget::create(Vec(26-15, 60), module, SawOsc::PITCH_PARAM, -3.0f, 3.0f, 0.0f));
+//addParam(ParamWidget::create(Vec(26-15, 60), module, SawOsc::PITCH_PARAM, -4.75f, 4.75f, -0.75f));
+
//addParam(ParamWidget::create(Vec(26, 125), module, SawOsc::PW_PARAM, -4.0, 5.0, -4.0));
- addParam(ParamWidget::create(Vec(26-15, 125), module, SawOsc::PW_PARAM, -4.2, 5.0, -4.2));
+ addParam(ParamWidget::create(Vec(26-15, 120), module, SawOsc::PW_PARAM, -4.2f, 5.0f, -4.2f));
+
+ //BASE FREQ SWITCH
+ addParam(ParamWidget::create(Vec(18, 220), module, SawOsc::BASE_PARAM, 0.0f, 1.0f, 1.0f));
//INPUTS
- addInput(Port::create(Vec(33-15, 200), Port::INPUT, module, SawOsc::PW_INPUT));
+ addInput(Port::create(Vec(33-15, 180), Port::INPUT, module, SawOsc::PW_INPUT));
addInput(Port::create(Vec(33-15, 260), Port::INPUT, module, SawOsc::PITCH_INPUT));
//OUTPUTS
addOutput(Port::create(Vec(33-15, 310), Port::OUTPUT, module, SawOsc::OSC_OUTPUT));
diff --git a/src/SineOSC.cpp b/src/SineOSC.cpp
index 96cf1e0..920cda5 100755
--- a/src/SineOSC.cpp
+++ b/src/SineOSC.cpp
@@ -9,6 +9,7 @@
struct SineOsc : Module {
enum ParamIds {
FREQ_PARAM,
+ BASE_PARAM,
NUM_PARAMS
};
enum InputIds {
@@ -27,6 +28,8 @@ struct SineOsc : Module {
float phase = 0.0f;
float blinkPhase = 0.0f;
+ float freq = 0.0f;
+ int base_freq = 0;
SineOsc() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
void step() override;
@@ -36,10 +39,18 @@ struct SineOsc : Module {
void SineOsc::step() {
// Implement a simple sine oscillator
// Compute the frequency from the pitch parameter and input
+ base_freq = params[BASE_PARAM].value;
float pitch = params[FREQ_PARAM].value;
pitch += inputs[FREQ_CV].value;
pitch = clamp(pitch, -4.0f, 4.0f);
- float freq = 440.0f * powf(2.0f, pitch);
+
+ if(base_freq==1){
+ //Note A4
+ freq = 440.0f * powf(2.0f, pitch);
+ }else{
+ // Note C4
+ freq = 261.626f * powf(2.0f, pitch);
+ }
// Accumulate the phase
phase += freq / engineGetSampleRate();
if (phase >= 1.0f)
@@ -51,6 +62,7 @@ void SineOsc::step() {
//float sine = sinf(2 * M_PI * phase)+ sinf(2 * M_PI * phase * 2)*5;
//mod,like this it gives a unipolar saw-ish wave
//float sine = sinf(2.0 * M_PI * (phase * 0.125)) * 5.0;
+
outputs[OSC_OUTPUT].value = sine;
lights[FREQ_LIGHT].value = (outputs[OSC_OUTPUT].value > 0.0f) ? 1.0f : 0.0f;
@@ -74,7 +86,12 @@ SineOscWidget::SineOscWidget(SineOsc *module) : ModuleWidget(module) {
//LIGHT
addChild(ModuleLightWidget::create>(Vec(22-15, 57), module, SineOsc::FREQ_LIGHT));
//PARAMS
+ //addParam(ParamWidget::create(Vec(26-15, 60), module, SineOsc::FREQ_PARAM, -3.75f, 3.75f, -0.75f));
+ //addParam(ParamWidget::create(Vec(26-15, 60), module, SineOsc::FREQ_PARAM, -3.0f, 2.999934f, -0.000066f));
addParam(ParamWidget::create(Vec(26-15, 60), module, SineOsc::FREQ_PARAM, -3.0f, 3.0f, 0.0f));
+
+ //BASE FREQ SWITCH
+ addParam(ParamWidget::create(Vec(18, 220), module, SineOsc::BASE_PARAM, 0.0f, 1.0f, 1.0f));
//INPUTS
addInput(Port::create(Vec(33-15, 260), Port::INPUT, module, SineOsc::FREQ_CV));
//OUTPUTS
diff --git a/src/ZeroCV2T.cpp b/src/ZeroCV2T.cpp
new file mode 100755
index 0000000..fe35054
--- /dev/null
+++ b/src/ZeroCV2T.cpp
@@ -0,0 +1,234 @@
+//**************************************************************************************
+//CV to Trigger convenrter module for VCV Rack by Alfredo Santamaria - AS - https://github.com/AScustomWorks/AS
+//
+//
+//**************************************************************************************
+#include "AS.hpp"
+#include "dsp/digital.hpp"
+
+struct ZeroCV2T : Module {
+ enum ParamIds {
+ TRIG_SWITCH_1,
+ TRIG_SWITCH_2,
+ TRIG_SWITCH_3,
+ TRIG_SWITCH_4,
+ NUM_PARAMS
+ };
+ enum InputIds {
+ CV_IN_1,
+ CV_IN_2,
+ CV_IN_3,
+ CV_IN_4,
+ NUM_INPUTS
+ };
+ enum OutputIds {
+ TRIG_OUT_1,
+ TRIG_OUT_2,
+ TRIG_OUT_3,
+ TRIG_OUT_4,
+ NUM_OUTPUTS
+ };
+ enum LightIds {
+ TRIG_LED_1,
+ TRIG_LED_2,
+ TRIG_LED_3,
+ TRIG_LED_4,
+ NUM_LIGHTS
+ };
+
+ SchmittTrigger trig_1, trig_2, trig_3, trig_4;
+
+ PulseGenerator trigPulse1, trigPulse2, trigPulse3, trigPulse4;
+ bool trig_pulse_1 = false;
+ bool trig_pulse_2 = false;
+ bool trig_pulse_3 = false;
+ bool trig_pulse_4 = false;
+
+ float trigger_length = 0.0001f;
+
+ const float lightLambda = 0.075f;
+ float trigLight1 = 0.0f;
+ float trigLight2 = 0.0f;
+ float trigLight3 = 0.0f;
+ float trigLight4 = 0.0f;
+
+ bool cv_1_engaged = false;
+ bool cv_2_engaged = false;
+ bool cv_3_engaged = false;
+ bool cv_4_engaged = false;
+
+ float current_cv_1_volts = 0.0f;
+ float current_cv_2_volts = 0.0f;
+ float current_cv_3_volts = 0.0f;
+ float current_cv_4_volts = 0.0f;
+ float trigger_treshold = 0.0005f;
+
+ ZeroCV2T() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {}
+
+ void step() override;
+};
+
+
+void ZeroCV2T::step() {
+
+ //CV TRIG 1
+ if ( trig_1.process( params[TRIG_SWITCH_1].value ) ) {
+ trigLight1 = 1.0;
+ trigPulse1.trigger( trigger_length );
+ }
+ current_cv_1_volts = inputs[CV_IN_1].value;
+
+ if ( fabs( current_cv_1_volts ) < trigger_treshold ){
+ if(!cv_1_engaged){
+ cv_1_engaged = true;
+ trigLight1 = 1.0;
+ trigPulse1.trigger( trigger_length );
+ // send trigger
+ }
+ } else {
+ if ( fabs( current_cv_1_volts ) > trigger_treshold ) {
+ // reenable trigger
+ cv_1_engaged = false;
+ }
+ }
+
+ trigLight1 -= trigLight1 / lightLambda / engineGetSampleRate();
+ lights[TRIG_LED_1].value = trigLight1;
+ trig_pulse_1 = trigPulse1.process( 1.0 / engineGetSampleRate() );
+ outputs[TRIG_OUT_1].value = ( trig_pulse_1 ? 10.0f : 0.0f );
+
+ //CV 2 TRIG 2
+ if ( trig_2.process( params[TRIG_SWITCH_2].value ) ) {
+ trigLight2 = 1.0;
+ trigPulse2.trigger( trigger_length );
+ }
+ current_cv_2_volts = inputs[CV_IN_2].value;
+
+ if ( fabs( current_cv_2_volts ) < trigger_treshold ){
+ if(!cv_2_engaged){
+ cv_2_engaged = true;
+ trigLight2 = 1.0;
+ trigPulse2.trigger( trigger_length );
+ // send trigger
+ }
+ } else {
+ if ( fabs( current_cv_2_volts ) > trigger_treshold ) {
+ // reenable trigger
+ cv_2_engaged = false;
+ }
+ }
+
+ trigLight2 -= trigLight2 / lightLambda / engineGetSampleRate();
+ lights[TRIG_LED_2].value = trigLight2;
+ trig_pulse_2 = trigPulse2.process( 1.0 / engineGetSampleRate() );
+ outputs[TRIG_OUT_2].value = ( trig_pulse_2 ? 10.0f : 0.0f );
+
+
+ //CV 2 TRIG 3
+ if ( trig_3.process( params[TRIG_SWITCH_3].value ) ) {
+ trigLight3 = 1.0;
+ trigPulse3.trigger( trigger_length );
+ }
+ current_cv_3_volts = inputs[CV_IN_3].value;
+
+ if ( fabs( current_cv_3_volts ) < trigger_treshold ){
+ if(!cv_3_engaged){
+ cv_3_engaged = true;
+ trigLight3 = 1.0;
+ trigPulse3.trigger( trigger_length );
+ // send trigger
+ }
+ } else {
+ if ( fabs( current_cv_3_volts ) > trigger_treshold ) {
+ // reenable trigger
+ cv_3_engaged = false;
+ }
+ }
+
+ trigLight3 -= trigLight3 / lightLambda / engineGetSampleRate();
+ lights[TRIG_LED_3].value = trigLight3;
+ trig_pulse_3 = trigPulse3.process( 1.0 / engineGetSampleRate() );
+ outputs[TRIG_OUT_3].value = ( trig_pulse_3 ? 10.0f : 0.0f );
+
+ //CV 2 TRIG 4
+ if ( trig_4.process( params[TRIG_SWITCH_4].value ) ) {
+ trigLight4 = 1.0;
+ trigPulse4.trigger( trigger_length );
+ }
+ current_cv_4_volts = inputs[CV_IN_4].value;
+
+ if ( fabs( current_cv_4_volts ) < trigger_treshold ){
+ if(!cv_4_engaged){
+ cv_4_engaged = true;
+ trigLight4 = 1.0;
+ trigPulse4.trigger( trigger_length );
+ // send trigger
+ }
+ } else {
+ if ( fabs( current_cv_4_volts ) > trigger_treshold ) {
+ // reenable trigger
+ cv_4_engaged = false;
+ }
+ }
+
+ trigLight4 -= trigLight4 / lightLambda / engineGetSampleRate();
+ lights[TRIG_LED_4].value = trigLight4;
+ trig_pulse_4 = trigPulse4.process( 1.0 / engineGetSampleRate() );
+ outputs[TRIG_OUT_4].value = ( trig_pulse_4 ? 10.0f : 0.0f );
+
+
+}
+
+struct ZeroCV2TWidget : ModuleWidget
+{
+ ZeroCV2TWidget(ZeroCV2T *module);
+};
+
+
+ZeroCV2TWidget::ZeroCV2TWidget(ZeroCV2T *module) : ModuleWidget(module) {
+
+ setPanel(SVG::load(assetPlugin(plugin, "res/ZeroCV2T.svg")));
+
+ //SCREWS - SPECIAL SPACING FOR RACK WIDTH*4
+ addChild(Widget::create(Vec(0, 0)));
+ addChild(Widget::create(Vec(box.size.x - RACK_GRID_WIDTH, 0)));
+ addChild(Widget::create(Vec(0, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
+ addChild(Widget::create(Vec(box.size.x - RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
+
+const int gp_offset = 75;
+ //CV 2 TRIG 1
+ //SWITCH & LED
+ addParam(ParamWidget::create(Vec(6, 101), module, ZeroCV2T::TRIG_SWITCH_1 , 0.0f, 1.0f, 0.0f));
+ addChild(ModuleLightWidget::create>(Vec(6+2.2, 103.2), module, ZeroCV2T::TRIG_LED_1));
+ //INPUTS
+ addInput(Port::create(Vec(18,60), Port::INPUT, module, ZeroCV2T::CV_IN_1));
+ //OUTPUTS
+ addOutput(Port::create(Vec(32, 100), Port::OUTPUT, module, ZeroCV2T::TRIG_OUT_1));
+ //CV 2 TRIG 2
+ //SWITCH & LED
+ addParam(ParamWidget::create(Vec(6, 101+gp_offset*1), module, ZeroCV2T::TRIG_SWITCH_2 , 0.0f, 1.0f, 0.0f));
+ addChild(ModuleLightWidget::create>(Vec(6+2.2, 103.2+gp_offset*1), module, ZeroCV2T::TRIG_LED_2));
+ //INPUTS
+ addInput(Port::create(Vec(18,60+gp_offset*1), Port::INPUT, module, ZeroCV2T::CV_IN_2));
+ //OUTPUTS
+ addOutput(Port::create(Vec(32, 100+gp_offset*1), Port::OUTPUT, module, ZeroCV2T::TRIG_OUT_2));
+ //CV 2 TRIG 3
+ //SWITCH & LED
+ addParam(ParamWidget::create(Vec(6, 101+gp_offset*2), module, ZeroCV2T::TRIG_SWITCH_3 , 0.0f, 1.0f, 0.0f));
+ addChild(ModuleLightWidget::create>(Vec(6+2.2, 103.2+gp_offset*2), module, ZeroCV2T::TRIG_LED_3));
+ //INPUTS
+ addInput(Port::create(Vec(18,60+gp_offset*2), Port::INPUT, module, ZeroCV2T::CV_IN_3));
+ //OUTPUTS
+ addOutput(Port::create(Vec(32, 100+gp_offset*2), Port::OUTPUT, module, ZeroCV2T::TRIG_OUT_3));
+ //CV 2 TRIG 4
+ //SWITCH & LED
+ addParam(ParamWidget::create(Vec(6, 101+gp_offset*3), module, ZeroCV2T::TRIG_SWITCH_4 , 0.0f, 1.0f, 0.0f));
+ addChild(ModuleLightWidget::create>(Vec(6+2.2, 103.2+gp_offset*3), module, ZeroCV2T::TRIG_LED_4));
+ //INPUTS
+ addInput(Port::create(Vec(18,60+gp_offset*3), Port::INPUT, module, ZeroCV2T::CV_IN_4));
+ //OUTPUTS
+ addOutput(Port::create(Vec(32, 100+gp_offset*3), Port::OUTPUT, module, ZeroCV2T::TRIG_OUT_4));
+
+}
+
+Model *modelZeroCV2T = Model::create("AS", "ZeroCV2T", "Zero Crossing CV to Trigger Switch", SWITCH_TAG);
\ No newline at end of file