Browse Source

Added Kickall prototype (lots to fix!)

tags/v1.1.0^2
hemmer 4 years ago
parent
commit
def1172533
8 changed files with 2028 additions and 3 deletions
  1. +6
    -0
      plugin.json
  2. +85
    -0
      res/BefacoTinyKnobGrey.svg
  3. +105
    -0
      res/Davies1900hLargeGrey.svg
  4. +1623
    -0
      res/Kickall.svg
  5. +20
    -3
      src/Common.hpp
  6. +187
    -0
      src/Kickall.cpp
  7. +1
    -0
      src/plugin.cpp
  8. +1
    -0
      src/plugin.hpp

+ 6
- 0
plugin.json View File

@@ -116,6 +116,12 @@
"name": "ChoppingKinky",
"description": "",
"tags": []
},
{
"slug": "Kickall",
"name": "Kickall",
"description": "",
"tags": []
}
]
}

+ 85
- 0
res/BefacoTinyKnobGrey.svg View File

@@ -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>

+ 105
- 0
res/Davies1900hLargeGrey.svg View File

@@ -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>

+ 1623
- 0
res/Kickall.svg
File diff suppressed because it is too large
View File


+ 20
- 3
src/Common.hpp View File

@@ -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 {
BefacoOutputPort() {
BefacoOutputPort() {
setSvg(APP->window->loadSvg(asset::plugin(pluginInstance, "res/BefacoOutputPort.svg")));
}
};

struct BefacoInputPort : app::SvgPort {
BefacoInputPort() {
BefacoInputPort() {
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.

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>
class AAFilter {
@@ -86,6 +100,7 @@ private:

/**
* Base class for oversampling of any order
* source: https://github.com/jatinchowdhury18/ChowDSP-VCV/blob/master/src/shared/oversampling.hpp
*/
class BaseOversampling {
public:
@@ -170,6 +185,8 @@ private:
osBuffer[k] = processSample(osBuffer[k]);
float y = oversample.downsample();
@endcode

source (modified): https://github.com/jatinchowdhury18/ChowDSP-VCV/blob/master/src/shared/VariableOversampling.hpp
*/
template<int filtN = 4>
class VariableOversampling {


+ 187
- 0
src/Kickall.cpp View File

@@ -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");

+ 1
- 0
src/plugin.cpp View File

@@ -16,4 +16,5 @@ void init(rack::Plugin *p) {
p->addModel(modelPercall);
p->addModel(modelHexmixVCA);
p->addModel(modelChoppingKinky);
p->addModel(modelKickall);
}

+ 1
- 0
src/plugin.hpp View File

@@ -16,6 +16,7 @@ extern Model *modelDualAtenuverter;
extern Model *modelPercall;
extern Model *modelHexmixVCA;
extern Model *modelChoppingKinky;
extern Model *modelKickall;

struct Knurlie : SvgScrew {
Knurlie() {


Loading…
Cancel
Save