@@ -116,6 +116,12 @@ | |||||
"name": "ChoppingKinky", | "name": "ChoppingKinky", | ||||
"description": "", | "description": "", | ||||
"tags": [] | "tags": [] | ||||
}, | |||||
{ | |||||
"slug": "Kickall", | |||||
"name": "Kickall", | |||||
"description": "", | |||||
"tags": [] | |||||
} | } | ||||
] | ] | ||||
} | } |
@@ -0,0 +1,85 @@ | |||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||||
<svg | |||||
xmlns:dc="http://purl.org/dc/elements/1.1/" | |||||
xmlns:cc="http://creativecommons.org/ns#" | |||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | |||||
xmlns:svg="http://www.w3.org/2000/svg" | |||||
xmlns="http://www.w3.org/2000/svg" | |||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | |||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | |||||
width="9.0000019mm" | |||||
height="9.0000801mm" | |||||
viewBox="0 0 9.0000016 9.00008" | |||||
version="1.1" | |||||
id="svg113936" | |||||
inkscape:version="1.0.2-2 (e86c870879, 2021-01-15)" | |||||
sodipodi:docname="BefacoTinyKnobGrey.svg"> | |||||
<defs | |||||
id="defs113930" /> | |||||
<sodipodi:namedview | |||||
id="base" | |||||
pagecolor="#ffffff" | |||||
bordercolor="#666666" | |||||
borderopacity="1.0" | |||||
inkscape:pageopacity="0.0" | |||||
inkscape:pageshadow="2" | |||||
inkscape:zoom="7.919596" | |||||
inkscape:cx="-34.401622" | |||||
inkscape:cy="28.745327" | |||||
inkscape:document-units="mm" | |||||
inkscape:current-layer="layer1" | |||||
showgrid="false" | |||||
fit-margin-top="0" | |||||
fit-margin-left="0" | |||||
fit-margin-right="0" | |||||
fit-margin-bottom="0" | |||||
inkscape:window-width="2560" | |||||
inkscape:window-height="1393" | |||||
inkscape:window-x="0" | |||||
inkscape:window-y="0" | |||||
inkscape:window-maximized="0" | |||||
inkscape:document-rotation="0" /> | |||||
<metadata | |||||
id="metadata113933"> | |||||
<rdf:RDF> | |||||
<cc:Work | |||||
rdf:about=""> | |||||
<dc:format>image/svg+xml</dc:format> | |||||
<dc:type | |||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | |||||
<dc:title></dc:title> | |||||
</cc:Work> | |||||
</rdf:RDF> | |||||
</metadata> | |||||
<g | |||||
inkscape:label="Layer 1" | |||||
inkscape:groupmode="layer" | |||||
id="layer1" | |||||
transform="translate(-111.86932,-85.795053)"> | |||||
<path | |||||
inkscape:connector-curvature="0" | |||||
style="fill:#d4d4d4;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.28209424" | |||||
d="m 120.10511,92.798549 c 1.38512,-2.062815 0.83525,-4.854005 -1.22757,-6.23803 -2.0617,-1.384026 -4.86062,-0.840773 -6.24463,1.222041 -1.38514,2.062814 -0.83306,4.866126 1.22866,6.251255 2.06282,1.384023 4.8595,0.827547 6.24354,-1.235266" | |||||
id="path109730" /> | |||||
<path | |||||
inkscape:connector-curvature="0" | |||||
style="fill:#606060;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.28209424" | |||||
d="m 120.02026,91.143448 c -0.46281,2.022043 -2.47716,3.285957 -4.49919,2.823148 -2.02205,-0.462813 -3.28598,-2.47714 -2.82314,-4.499182 0.46281,-2.020944 2.47713,-3.285958 4.49918,-2.82315 2.02093,0.462812 3.28594,2.477141 2.82315,4.499184" | |||||
id="path109732" /> | |||||
<path | |||||
inkscape:connector-curvature="0" | |||||
style="fill:none;stroke:#7f7878;stroke-width:0.11481237;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1" | |||||
d="m 120.02026,91.143463 c -0.46281,2.022042 -2.47715,3.285956 -4.49919,2.823145 -2.02204,-0.462811 -3.28595,-2.47714 -2.82314,-4.499183 0.46281,-2.020941 2.47714,-3.285957 4.49918,-2.823145 2.02094,0.46281 3.28596,2.47714 2.82315,4.499183 z m 0,0" | |||||
id="path109734" /> | |||||
<path | |||||
inkscape:connector-curvature="0" | |||||
style="fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.28209424" | |||||
d="m 116.20648,88.009558 c -0.11239,-0.07603 -0.14328,-0.229201 -0.0672,-0.342701 0.0761,-0.113495 0.23029,-0.143251 0.34379,-0.06722 0.11356,0.07603 0.14325,0.229201 0.0672,0.342701 -0.076,0.113495 -0.23031,0.14325 -0.34379,0.06722" | |||||
id="path109736" /> | |||||
<path | |||||
inkscape:connector-curvature="0" | |||||
style="fill:#ffffff;stroke:#ffffff;stroke-width:0.46912277;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;fill-opacity:1" | |||||
d="m 116.20647,88.009571 c -0.11239,-0.07603 -0.14326,-0.229202 -0.0672,-0.3427 0.076,-0.113495 0.23032,-0.14325 0.34381,-0.06722 0.11356,0.07602 0.14325,0.229201 0.0672,0.3427 -0.076,0.113495 -0.2303,0.143251 -0.3438,0.06722 z m 0,0" | |||||
id="path109738" /> | |||||
</g> | |||||
</svg> |
@@ -0,0 +1,105 @@ | |||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||||
<svg | |||||
xmlns:dc="http://purl.org/dc/elements/1.1/" | |||||
xmlns:cc="http://creativecommons.org/ns#" | |||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" | |||||
xmlns:svg="http://www.w3.org/2000/svg" | |||||
xmlns="http://www.w3.org/2000/svg" | |||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd" | |||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape" | |||||
width="54" | |||||
height="54.002399" | |||||
viewBox="0 0 14.2875 14.288134" | |||||
version="1.1" | |||||
id="svg16908" | |||||
inkscape:version="1.0.2-2 (e86c870879, 2021-01-15)" | |||||
sodipodi:docname="Davies1900hLargeGrey.svg"> | |||||
<defs | |||||
id="defs16902"> | |||||
<clipPath | |||||
clipPathUnits="userSpaceOnUse" | |||||
id="clipPath6367"> | |||||
<path | |||||
d="M 0,3193 H 2089 V 0 H 0 Z" | |||||
id="path6365" | |||||
inkscape:connector-curvature="0" /> | |||||
</clipPath> | |||||
</defs> | |||||
<sodipodi:namedview | |||||
id="base" | |||||
pagecolor="#ffffff" | |||||
bordercolor="#666666" | |||||
borderopacity="1.0" | |||||
inkscape:pageopacity="0.0" | |||||
inkscape:pageshadow="2" | |||||
inkscape:zoom="15.839192" | |||||
inkscape:cx="4.7207333" | |||||
inkscape:cy="8.7180405" | |||||
inkscape:document-units="mm" | |||||
inkscape:current-layer="layer1" | |||||
showgrid="false" | |||||
fit-margin-top="0" | |||||
fit-margin-left="0" | |||||
fit-margin-right="0" | |||||
fit-margin-bottom="0" | |||||
inkscape:window-width="2560" | |||||
inkscape:window-height="1393" | |||||
inkscape:window-x="43" | |||||
inkscape:window-y="161" | |||||
inkscape:window-maximized="0" | |||||
units="px" | |||||
inkscape:document-rotation="0" /> | |||||
<metadata | |||||
id="metadata16905"> | |||||
<rdf:RDF> | |||||
<cc:Work | |||||
rdf:about=""> | |||||
<dc:format>image/svg+xml</dc:format> | |||||
<dc:type | |||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /> | |||||
<dc:title /> | |||||
</cc:Work> | |||||
</rdf:RDF> | |||||
</metadata> | |||||
<g | |||||
inkscape:label="Layer 1" | |||||
inkscape:groupmode="layer" | |||||
id="layer1" | |||||
transform="translate(-231.61418,-118.28792)"> | |||||
<g | |||||
id="g2004" | |||||
transform="matrix(0.39687059,0,0,-0.39687059,-305.70597,1064.5469)" | |||||
style="stroke-width:0.8894587;stroke-miterlimit:4;stroke-dasharray:none"> | |||||
<g | |||||
transform="translate(1389.8926,2366.2998)" | |||||
id="g6455" | |||||
style="stroke-width:0.8894587;stroke-miterlimit:4;stroke-dasharray:none"> | |||||
<path | |||||
inkscape:connector-curvature="0" | |||||
id="path6457" | |||||
style="fill:#a9a9a9;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.8894587;stroke-miterlimit:4;stroke-dasharray:none" | |||||
d="m 0,0 c 0,-9.941 -8.059,-18 -18,-18 -9.941,0 -18,8.059 -18,18 0,9.941 8.059,18 18,18 C -8.059,18 0,9.941 0,0" /> | |||||
</g> | |||||
<g | |||||
transform="translate(1389.791,2368.2021)" | |||||
id="g6459" | |||||
style="stroke-width:0.8894587;stroke-miterlimit:4;stroke-dasharray:none"> | |||||
<path | |||||
inkscape:connector-curvature="0" | |||||
id="path6461" | |||||
style="fill:#606060;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.8894587;stroke-miterlimit:4;stroke-dasharray:none" | |||||
d="m 0,0 c -0.79,1.279 -2.12,2.537 -2.86,4.327 -0.74,1.784 -0.691,3.609 -1.033,5.067 -0.805,0.997 -1.711,1.902 -2.709,2.708 -1.459,0.341 -3.282,0.293 -5.068,1.033 -1.79,0.742 -3.048,2.069 -4.325,2.86 -0.625,0.066 -1.26,0.104 -1.902,0.104 -0.644,0 -1.279,-0.038 -1.903,-0.104 -1.279,-0.791 -2.537,-2.118 -4.327,-2.86 -1.784,-0.74 -3.607,-0.692 -5.067,-1.033 -0.997,-0.806 -1.904,-1.711 -2.708,-2.708 -0.342,-1.458 -0.294,-3.283 -1.035,-5.067 -0.74,-1.79 -2.069,-3.048 -2.858,-4.327 -0.066,-0.625 -0.103,-1.26 -0.103,-1.902 0,-0.643 0.037,-1.278 0.103,-1.905 0.789,-1.277 2.118,-2.535 2.858,-4.325 0.741,-1.784 0.693,-3.609 1.035,-5.066 0.804,-0.998 1.711,-1.904 2.708,-2.709 1.46,-0.342 3.283,-0.293 5.067,-1.032 1.79,-0.743 3.048,-2.071 4.327,-2.861 0.624,-0.065 1.259,-0.103 1.903,-0.103 0.642,0 1.277,0.038 1.902,0.103 1.277,0.79 2.535,2.118 4.325,2.861 1.786,0.739 3.609,0.69 5.068,1.032 0.998,0.805 1.904,1.711 2.709,2.709 0.342,1.457 0.293,3.282 1.033,5.066 0.74,1.79 2.07,3.048 2.86,4.325 0.065,0.627 0.102,1.262 0.102,1.905 C 0.102,-1.26 0.065,-0.625 0,0" /> | |||||
</g> | |||||
<g | |||||
transform="translate(1372.4912,2384.2314)" | |||||
id="g6463" | |||||
style="stroke-width:0.8894587;stroke-miterlimit:4;stroke-dasharray:none"> | |||||
<path | |||||
inkscape:connector-curvature="0" | |||||
id="path6465" | |||||
style="fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:0.8894587;stroke-miterlimit:4;stroke-dasharray:none" | |||||
d="M 0,0 C -0.195,0.045 -0.393,0.069 -0.598,0.069 -0.804,0.069 -1.002,0.045 -1.196,0 V -18.157 H 0 Z" /> | |||||
</g> | |||||
</g> | |||||
</g> | |||||
</svg> |
@@ -19,14 +19,28 @@ struct BefacoTinyKnobWhite : app::SvgKnob { | |||||
} | } | ||||
}; | }; | ||||
struct BefacoTinyKnobGrey : app::SvgKnob { | |||||
BefacoTinyKnobGrey() { | |||||
minAngle = -0.8 * M_PI; | |||||
maxAngle = 0.8 * M_PI; | |||||
setSvg(APP->window->loadSvg(asset::plugin(pluginInstance, "res/BefacoTinyKnobGrey.svg"))); | |||||
} | |||||
}; | |||||
struct Davies1900hLargeGreyKnob : Davies1900hKnob { | |||||
Davies1900hLargeGreyKnob() { | |||||
setSvg(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Davies1900hLargeGrey.svg"))); | |||||
} | |||||
}; | |||||
struct BefacoOutputPort : app::SvgPort { | struct BefacoOutputPort : app::SvgPort { | ||||
BefacoOutputPort() { | |||||
BefacoOutputPort() { | |||||
setSvg(APP->window->loadSvg(asset::plugin(pluginInstance, "res/BefacoOutputPort.svg"))); | setSvg(APP->window->loadSvg(asset::plugin(pluginInstance, "res/BefacoOutputPort.svg"))); | ||||
} | } | ||||
}; | }; | ||||
struct BefacoInputPort : app::SvgPort { | struct BefacoInputPort : app::SvgPort { | ||||
BefacoInputPort() { | |||||
BefacoInputPort() { | |||||
setSvg(APP->window->loadSvg(asset::plugin(pluginInstance, "res/BefacoInputPort.svg"))); | setSvg(APP->window->loadSvg(asset::plugin(pluginInstance, "res/BefacoInputPort.svg"))); | ||||
} | } | ||||
}; | }; | ||||
@@ -36,7 +50,7 @@ struct BefacoInputPort : app::SvgPort { | |||||
The template parameter N should be 1/2 the desired filter order. | The template parameter N should be 1/2 the desired filter order. | ||||
Currently uses an 2*N-th order Butterworth filter. | Currently uses an 2*N-th order Butterworth filter. | ||||
@TODO: implement Chebyshev, Elliptic filter options. | |||||
source: https://github.com/jatinchowdhury18/ChowDSP-VCV/blob/master/src/shared/AAFilter.hpp | |||||
*/ | */ | ||||
template<int N> | template<int N> | ||||
class AAFilter { | class AAFilter { | ||||
@@ -86,6 +100,7 @@ private: | |||||
/** | /** | ||||
* Base class for oversampling of any order | * Base class for oversampling of any order | ||||
* source: https://github.com/jatinchowdhury18/ChowDSP-VCV/blob/master/src/shared/oversampling.hpp | |||||
*/ | */ | ||||
class BaseOversampling { | class BaseOversampling { | ||||
public: | public: | ||||
@@ -170,6 +185,8 @@ private: | |||||
osBuffer[k] = processSample(osBuffer[k]); | osBuffer[k] = processSample(osBuffer[k]); | ||||
float y = oversample.downsample(); | float y = oversample.downsample(); | ||||
@endcode | @endcode | ||||
source (modified): https://github.com/jatinchowdhury18/ChowDSP-VCV/blob/master/src/shared/VariableOversampling.hpp | |||||
*/ | */ | ||||
template<int filtN = 4> | template<int filtN = 4> | ||||
class VariableOversampling { | class VariableOversampling { | ||||
@@ -0,0 +1,187 @@ | |||||
#include "plugin.hpp" | |||||
#include "Common.hpp" | |||||
struct ADEnvelope { | |||||
enum Stage { | |||||
STAGE_OFF, | |||||
STAGE_ATTACK, | |||||
STAGE_DECAY | |||||
}; | |||||
Stage stage = STAGE_OFF; | |||||
float env = 0.f; | |||||
float attackTime = 0.1, decayTime = 0.1; | |||||
ADEnvelope() { }; | |||||
void process(const float& sampleTime) { | |||||
if (stage == STAGE_OFF) { | |||||
env = 0.0f; | |||||
} | |||||
else if (stage == STAGE_ATTACK) { | |||||
env += sampleTime / attackTime; | |||||
} | |||||
else if (stage == STAGE_DECAY) { | |||||
env -= sampleTime / decayTime; | |||||
} | |||||
if (env >= 1.0f) { | |||||
stage = STAGE_DECAY; | |||||
env = 1.0f; | |||||
} | |||||
else if (env <= 0.0f) { | |||||
stage = STAGE_OFF; | |||||
env = 0.0f; | |||||
} | |||||
} | |||||
}; | |||||
struct Kickall : Module { | |||||
enum ParamIds { | |||||
TUNE_PARAM, | |||||
TRIGG_BUTTON_PARAM, | |||||
SHAPE_PARAM, | |||||
DECAY_PARAM, | |||||
TIME_PARAM, | |||||
BEND_PARAM, | |||||
NUM_PARAMS | |||||
}; | |||||
enum InputIds { | |||||
TRIGG_INPUT, | |||||
VOLUME_INPUT, | |||||
TUNE_INPUT, | |||||
SHAPE_INPUT, | |||||
DECAY_INPUT, | |||||
NUM_INPUTS | |||||
}; | |||||
enum OutputIds { | |||||
OUT_OUTPUT, | |||||
NUM_OUTPUTS | |||||
}; | |||||
enum LightIds { | |||||
ENV_LIGHT, | |||||
NUM_LIGHTS | |||||
}; | |||||
Kickall() { | |||||
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | |||||
// TODO: review this mapping, using displayBase multiplier seems more normal | |||||
configParam(TUNE_PARAM, FREQ_A0, FREQ_B2, 0.5 * (FREQ_A0 + FREQ_B2), "Tune", "Hz"); | |||||
configParam(TRIGG_BUTTON_PARAM, 0.f, 1.f, 0.f, "Manual trigger"); | |||||
configParam(SHAPE_PARAM, 0.f, 1.f, 0.f, ""); | |||||
configParam(DECAY_PARAM, 0.01f, 1.f, 0.01f, "VCA Envelope decay time"); | |||||
configParam(TIME_PARAM, 0.0079f, 0.076f, 0.0079f, "Pitch envelope decay time", "ms", 0.0f, 1000.f); | |||||
configParam(BEND_PARAM, 0.f, 1.f, 0.f, "Pitch envelope attenuator"); | |||||
volume.attackTime = 0.00165; | |||||
pitch.attackTime = 0.00165; | |||||
// calculate up/downsampling rates | |||||
onSampleRateChange(); | |||||
} | |||||
void onSampleRateChange() override { | |||||
// SampleRateConverter needs integer value | |||||
int sampleRate = APP->engine->getSampleRate(); | |||||
oversampler.reset(sampleRate); | |||||
} | |||||
float bendRange = 600; | |||||
float phase = 0.f; | |||||
ADEnvelope volume; | |||||
ADEnvelope pitch; | |||||
dsp::SchmittTrigger trigger; | |||||
static constexpr float FREQ_A0 = 27.5f; | |||||
static constexpr float FREQ_B2 = 123.471f; | |||||
static const int UPSAMPLE = 4; | |||||
Oversampling<UPSAMPLE> oversampler; | |||||
float shaperBuf[UPSAMPLE]; | |||||
void process(const ProcessArgs& args) override { | |||||
// TODO: check values | |||||
if (trigger.process(inputs[TRIGG_INPUT].getVoltage() / 2.0f + params[TRIGG_BUTTON_PARAM].getValue() * 10.0)) { | |||||
volume.stage = ADEnvelope::STAGE_ATTACK; | |||||
pitch.stage = ADEnvelope::STAGE_ATTACK; | |||||
} | |||||
float vcaGain = clamp(inputs[VOLUME_INPUT].getNormalVoltage(10.f) / 10.f, 0.f, 1.0f); | |||||
// pitch envelope | |||||
float bend = params[BEND_PARAM].getValue(); | |||||
pitch.decayTime = params[TIME_PARAM].getValue(); | |||||
pitch.process(args.sampleTime); | |||||
// volume envelope TODO: wire in decay CV | |||||
volume.decayTime = params[DECAY_PARAM].getValue(); | |||||
volume.process(args.sampleTime); | |||||
float freq = params[TUNE_PARAM].getValue(); | |||||
freq *= std::pow(2, inputs[TUNE_INPUT].getVoltage()); | |||||
//float kickFrequency = std::max(50.0f, params[TUNE_PARAM].getValue() + bendRange * bend * pitch.env); | |||||
float kickFrequency = std::max(50.0f, freq + bendRange * bend * pitch.env); | |||||
phase += args.sampleTime * kickFrequency; | |||||
if (phase > 1.0f) { | |||||
phase -= 1.0f; | |||||
} | |||||
// TODO: faster approximation | |||||
float wave = std::sin(2.0 * M_PI * phase); | |||||
oversampler.upsample(wave); | |||||
float* inputBuf = oversampler.getOSBuffer(); | |||||
float shape = clamp(inputs[SHAPE_INPUT].getVoltage() / 2.f + params[SHAPE_PARAM].getValue() * 5.0f, 0.0f, 10.0f); | |||||
shape = clamp(shape, 0.f, 5.0f) * 0.2f; | |||||
shape *= 0.99f; | |||||
const float shapeB = (1.0f - shape) / (1.0f + shape); | |||||
const float shapeA = (4.0f * shape) / ((1.0f - shape) * (1.0f + shape)); | |||||
for (int i = 0; i < UPSAMPLE; ++i) { | |||||
inputBuf[i] = inputBuf[i] * (shapeA + shapeB) / ((std::abs(inputBuf[i]) * shapeA) + shapeB); | |||||
} | |||||
float out = volume.env * oversampler.downsample() * 5.0f * vcaGain; | |||||
outputs[OUT_OUTPUT].setVoltage(out); | |||||
lights[ENV_LIGHT].setBrightness(volume.stage); | |||||
} | |||||
}; | |||||
struct KickallWidget : ModuleWidget { | |||||
KickallWidget(Kickall* module) { | |||||
setModule(module); | |||||
setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Kickall.svg"))); | |||||
addChild(createWidget<Knurlie>(Vec(RACK_GRID_WIDTH, 0))); | |||||
addChild(createWidget<Knurlie>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH))); | |||||
addParam(createParamCentered<BefacoTinyKnobGrey>(mm2px(Vec(8.76, 29.068)), module, Kickall::TUNE_PARAM)); | |||||
addParam(createParamCentered<BefacoPush>(mm2px(Vec(22.651, 29.068)), module, Kickall::TRIGG_BUTTON_PARAM)); | |||||
addParam(createParamCentered<Davies1900hLargeGreyKnob>(mm2px(Vec(15.781, 49.278)), module, Kickall::SHAPE_PARAM)); | |||||
addParam(createParam<BefacoSlidePot>(mm2px(Vec(19.913, 64.004)), module, Kickall::DECAY_PARAM)); | |||||
addParam(createParamCentered<BefacoTinyKnobWhite>(mm2px(Vec(8.977, 71.626)), module, Kickall::TIME_PARAM)); | |||||
addParam(createParamCentered<BefacoTinyKnobWhite>(mm2px(Vec(8.977, 93.549)), module, Kickall::BEND_PARAM)); | |||||
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(5.715, 14.651)), module, Kickall::TRIGG_INPUT)); | |||||
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(15.748, 14.651)), module, Kickall::VOLUME_INPUT)); | |||||
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(5.697, 113.286)), module, Kickall::TUNE_INPUT)); | |||||
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(15.794, 113.286)), module, Kickall::SHAPE_INPUT)); | |||||
addInput(createInputCentered<BefacoInputPort>(mm2px(Vec(25.891, 113.286)), module, Kickall::DECAY_INPUT)); | |||||
addOutput(createOutputCentered<BefacoOutputPort>(mm2px(Vec(25.781, 14.651)), module, Kickall::OUT_OUTPUT)); | |||||
addChild(createLightCentered<SmallLight<RedLight>>(mm2px(Vec(15.723, 34.971)), module, Kickall::ENV_LIGHT)); | |||||
} | |||||
}; | |||||
Model* modelKickall = createModel<Kickall, KickallWidget>("Kickall"); |
@@ -16,4 +16,5 @@ void init(rack::Plugin *p) { | |||||
p->addModel(modelPercall); | p->addModel(modelPercall); | ||||
p->addModel(modelHexmixVCA); | p->addModel(modelHexmixVCA); | ||||
p->addModel(modelChoppingKinky); | p->addModel(modelChoppingKinky); | ||||
p->addModel(modelKickall); | |||||
} | } |
@@ -16,6 +16,7 @@ extern Model *modelDualAtenuverter; | |||||
extern Model *modelPercall; | extern Model *modelPercall; | ||||
extern Model *modelHexmixVCA; | extern Model *modelHexmixVCA; | ||||
extern Model *modelChoppingKinky; | extern Model *modelChoppingKinky; | ||||
extern Model *modelKickall; | |||||
struct Knurlie : SvgScrew { | struct Knurlie : SvgScrew { | ||||
Knurlie() { | Knurlie() { | ||||