diff --git a/res/Octave.svg b/res/Octave.svg
index ac3c344..680da88 100644
--- a/res/Octave.svg
+++ b/res/Octave.svg
@@ -9,15 +9,15 @@
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="15.23972mm"
- height="128.49931mm"
- viewBox="0 0 15.23972 128.49931"
+ width="14.8mm"
+ height="128.5mm"
+ viewBox="0 0 14.8 128.5"
version="1.1"
- id="svg55191"
- inkscape:version="0.92.2 2405546, 2018-03-11"
+ id="svg4352"
+ inkscape:version="0.92.4 5da689c313, 2019-01-14"
sodipodi:docname="Octave.svg">
+ id="defs4346" />
+ inkscape:bbox-nodes="false" />
+ id="metadata4349">
@@ -61,108 +58,117 @@
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
- transform="translate(-90.65395,-49.809869)">
+ transform="translate(0,-168.5)">
+ d="M 0.09375,168.59371 H 15.14602 V 296.90698 H 0.09375 Z m 0,0"
+ id="path30861" />
+ d="M 15.23977,168.5 H 0 V 296.99931 H 15.23977 Z M 15.05371,296.81328 H 0.18606 V 168.68741 h 14.86765 z m 0,0"
+ id="path30863" />
+ d="m 4.6553698,178.11475 c 0.91504,0 1.5765,-0.68902 1.5765,-1.53238 v -0.005 c 0,-0.84336 -0.65596,-1.52687 -1.57097,-1.52687 -0.91503,0 -1.57649,0.68902 -1.57649,1.53238 v 0.011 c 0,0.84336 0.65596,1.52135 1.57096,1.52135 z m 0.006,-0.60083 c -0.52366,0 -0.89847,-0.42443 -0.89847,-0.93155 v -0.005 c 0,-0.50712 0.36377,-0.92604 0.89294,-0.92604 0.52366,0 0.893,0.42443 0.893,0.93155 v 0.011 c 0,0.50712 -0.36383,0.92053 -0.88747,0.92053 z m 0,0"
+ id="path53219" />
+ d="m 8.2112398,178.11475 c 0.47403,0 0.78825,-0.13781 1.05834,-0.36932 0.0551,-0.0551 0.11022,-0.13229 0.11022,-0.23702 0,-0.16537 -0.14332,-0.29766 -0.30866,-0.29766 -0.0772,0 -0.14335,0.0276 -0.19294,0.0717 -0.1874,0.14883 -0.36933,0.23151 -0.64492,0.23151 -0.50712,0 -0.85989,-0.42443 -0.85989,-0.93155 v -0.005 c 0,-0.50712 0.36377,-0.92604 0.85989,-0.92604 0.23149,0 0.42442,0.0772 0.60632,0.21497 0.0496,0.0276 0.10475,0.0606 0.19294,0.0606 0.1819,0 0.32522,-0.1378 0.32522,-0.31419 0,-0.11576 -0.0606,-0.20946 -0.12679,-0.25907 -0.24804,-0.18241 -0.5457,-0.30368 -0.99218,-0.30368 -0.90951,0 -1.5434,0.68902 -1.5434,1.53238 v 0.011 c 0,0.84887 0.6449,1.52135 1.51585,1.52135 z m 0,0"
+ id="path53215" />
+ d="m 10.68118,177.76197 c 0,0.1819 0.14333,0.33073 0.32523,0.33073 0.18187,0 0.32522,-0.14883 0.32522,-0.33073 v -2.06155 h 0.62836 c 0.16539,0 0.29768,-0.13229 0.29768,-0.29765 0,-0.16537 -0.13229,-0.30317 -0.29768,-0.30317 H 10.0528 c -0.1653702,0 -0.2976602,0.1378 -0.2976602,0.30317 0,0.16536 0.13229,0.29765 0.2976602,0.29765 h 0.62838 z m 0,0"
+ id="path53223" />
+ d="m 8.2544798,288.975 c 0,0.22048 -0.17913,0.40101 -0.40101,0.40101 -0.22185,0 -0.40103,-0.18053 -0.40103,-0.40101 0,-0.22187 0.17918,-0.40101 0.40103,-0.40101 0.22188,0 0.40101,0.17914 0.40101,0.40101"
+ id="path38469" />
+ d="m 4.9306498,290.30067 c -0.11713,0 -0.22323,-0.0661 -0.27559,-0.17088 l -1.00185,-2.00367 c -0.0772,-0.15296 -0.0151,-0.33761 0.1378,-0.41478 0.15158,-0.0758 0.33763,-0.0138 0.41341,0.1378 l 0.72623,1.45383 0.72623,-1.45383 c 0.0772,-0.15159 0.26183,-0.2136 0.41478,-0.1378 0.15161,0.0772 0.21363,0.26182 0.1378,0.41478 l -1.0032,2.00367 c -0.0524,0.10473 -0.15848,0.17088 -0.27561,0.17088"
+ id="path38471" />
+ d="m 10.43591,290.30067 c -0.11573,0 -0.22323,-0.0661 -0.27561,-0.17088 l -1.0018202,-2.00367 c -0.0758,-0.15296 -0.0151,-0.33761 0.13779,-0.41478 0.15158,-0.0758 0.33761,-0.0138 0.41341,0.1378 l 0.7262302,1.45383 0.72761,-1.45383 c 0.0758,-0.15159 0.26045,-0.2136 0.41343,-0.1378 0.15156,0.0772 0.21358,0.26182 0.1378,0.41478 l -1.00187,2.00367 c -0.0523,0.10473 -0.15984,0.17088 -0.27697,0.17088"
+ id="path38473" />
+ d="m 7.8328098,290.30067 c -0.7221,0 -1.31054,-0.58842 -1.31054,-1.31051 0,-0.72348 0.58844,-1.31052 1.31054,-1.31052 0.28662,0 0.55946,0.091 0.78684,0.26183 0.13645,0.10197 0.16399,0.29627 0.062,0.43133 -0.10197,0.13642 -0.29628,0.16398 -0.4327,0.062 -0.11991,-0.091 -0.26458,-0.13919 -0.41616,-0.13919 -0.38174,0 -0.69318,0.31144 -0.69318,0.69454 0,0.38309 0.31144,0.69315 0.69318,0.69315 0.15158,0 0.29625,-0.0469 0.41616,-0.13781 0.13642,-0.10197 0.33073,-0.0758 0.4327,0.0606 0.10197,0.13642 0.0744,0.33073 -0.062,0.4327 -0.22738,0.17088 -0.50022,0.26183 -0.78684,0.26183"
+ id="path38475" />
+ d="m 12.46164,273.41832 c 0,-0.54984 -0.45064,-0.99908 -1.00047,-0.99908 H 3.7786198 c -0.54985,0 -0.9990598,0.44924 -0.9990598,0.99908 v 11.67336 c 0,0.54984 0.4492098,1.00046 0.9990598,1.00046 H 11.46117 c 0.54983,0 1.00047,-0.45062 1.00047,-1.00046 z m 0,0"
+ id="path38477" />
+ d="m 5.9512798,275.25765 c 0.49606,0 0.85989,-0.37483 0.85989,-0.83234 0,-0.45751 -0.3583,-0.82682 -0.85439,-0.82682 -0.49609,0 -0.85439,0.37483 -0.85439,0.82682 v 0.006 c 0,0.45752 0.3583,0.82682 0.84889,0.82682 z m 0.006,-0.32522 c -0.28112,0 -0.48506,-0.23151 -0.48506,-0.50712 0,-0.27561 0.19844,-0.50161 0.47956,-0.50161 0.28662,0 0.49056,0.226 0.49056,0.50161 v 0.006 c 0,0.2756 -0.19843,0.50161 -0.48506,0.50161 z m 0,0"
+ id="path53243" />
+ d="m 7.9392798,275.25765 c 0.25905,0 0.42992,-0.0772 0.57327,-0.20395 0.0332,-0.0275 0.0606,-0.0717 0.0606,-0.12127 0,-0.0937 -0.0771,-0.16536 -0.16534,-0.16536 -0.0441,0 -0.0772,0.0165 -0.10475,0.0386 -0.10472,0.0827 -0.19843,0.12678 -0.35277,0.12678 -0.27008,0 -0.46302,-0.23151 -0.46302,-0.50712 0,-0.27561 0.19294,-0.50161 0.46302,-0.50161 0.12679,0 0.23154,0.0386 0.33073,0.11576 0.0275,0.0165 0.0551,0.0331 0.10475,0.0331 0.0992,0 0.17637,-0.0772 0.17637,-0.17088 0,-0.0662 -0.0331,-0.11575 -0.0716,-0.14332 -0.13229,-0.0992 -0.29215,-0.15985 -0.53469,-0.15985 -0.49607,0 -0.83786,0.37483 -0.83786,0.82683 v 0.005 c 0,0.46302 0.3528,0.82682 0.82135,0.82682 z m 0,0"
+ id="path53239" />
+ d="m 9.3362498,275.06472 c 0,0.0992 0.0771,0.17639 0.17637,0.17639 0.0992,0 0.1764,-0.0772 0.1764,-0.17639 v -1.11345 H 10.02525 c 0.0937,0 0.16534,-0.0717 0.16534,-0.16537 0,-0.0882 -0.0716,-0.15985 -0.16534,-0.15985 H 8.9944598 c -0.0882,0 -0.15983,0.0717 -0.15983,0.15985 0,0.0937 0.0716,0.16537 0.15983,0.16537 h 0.34179 z m 0,0"
+ id="path53247" />
+ d="m 6.5338098,259.70544 c 0,0.0772 0.0662,0.13781 0.1433,0.13781 0.0772,0 0.14332,-0.0606 0.14332,-0.13781 v -1.35047 c 0,-0.0772 -0.0661,-0.13781 -0.14332,-0.13781 -0.0771,0 -0.1433,0.0606 -0.1433,0.13781 z m 0,0"
+ id="path53255" />
+ d="m 7.3175898,259.70544 c 0,0.0772 0.0661,0.13781 0.14332,0.13781 0.0772,0 0.1378,-0.0606 0.1378,-0.13781 v -1.01974 l 0.82684,1.06935 c 0.0385,0.0496 0.0772,0.0882 0.1433,0.0882 h 0.0109 c 0.0771,0 0.1378,-0.0662 0.1378,-0.14331 v -1.34497 c 0,-0.0772 -0.0607,-0.1378 -0.1378,-0.1378 -0.0772,0 -0.13782,0.0606 -0.13782,0.1378 v 0.98667 l -0.80476,-1.04179 c -0.0386,-0.0496 -0.0772,-0.0827 -0.14335,-0.0827 h -0.0331 c -0.0772,0 -0.14333,0.0662 -0.14333,0.14332 z m 0,0"
+ id="path53251" />
+
-
-
+ style="display:inline;opacity:1;vector-effect:none;fill:#ffff00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.82156646;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:normal"
+ id="rect7595"
+ width="15.23977"
+ height="62.999779"
+ x="3.5527137e-15"
+ y="12.81713" />
+
+
+
diff --git a/src/Octave.cpp b/src/Octave.cpp
index 2bc6905..5175c6c 100644
--- a/src/Octave.cpp
+++ b/src/Octave.cpp
@@ -3,66 +3,64 @@
struct Octave : Module {
enum ParamIds {
+ OCTAVE_PARAM,
NUM_PARAMS
};
enum InputIds {
- CV_INPUT,
+ PITCH_INPUT,
+ OCTAVE_INPUT,
NUM_INPUTS
};
enum OutputIds {
- CV_OUTPUT,
+ PITCH_OUTPUT,
NUM_OUTPUTS
};
enum LightIds {
NUM_LIGHTS
};
- int octave = 0;
-
Octave() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
- }
-
- void onReset() override {
- octave = 0;
- }
-
- void onRandomize() override {
- octave = (random::u32() % 9) - 4;
+ configParam(OCTAVE_PARAM, -4.f, 4.f, 0.f, "Octave shift");
}
void process(const ProcessArgs &args) override {
- int channels = std::max(inputs[CV_INPUT].getChannels(), 1);
+ int channels = std::max(inputs[PITCH_INPUT].getChannels(), 1);
+ float octaveParam = params[OCTAVE_PARAM].getValue();
+
for (int c = 0; c < channels; c++) {
- float cv = inputs[CV_INPUT].getVoltage(c);
+ float octave = octaveParam + inputs[OCTAVE_INPUT].getPolyVoltage(c);
+ octave = std::round(octave);
+ float cv = inputs[PITCH_INPUT].getVoltage(c);
cv += octave;
- outputs[CV_OUTPUT].setVoltage(cv, c);
+ outputs[PITCH_OUTPUT].setVoltage(cv, c);
}
- outputs[CV_OUTPUT].setChannels(channels);
- }
-
- json_t *dataToJson() override {
- json_t *rootJ = json_object();
- json_object_set_new(rootJ, "octave", json_integer(octave));
- return rootJ;
+ outputs[PITCH_OUTPUT].setChannels(channels);
}
void dataFromJson(json_t *rootJ) override {
+ // In Fundamental 1.1.1 and earlier, the octave param was internal data.
json_t *octaveJ = json_object_get(rootJ, "octave");
- if (octaveJ)
- octave = json_integer_value(octaveJ);
+ if (octaveJ) {
+ params[OCTAVE_PARAM].setValue(json_integer_value(octaveJ));
+ }
}
};
-struct OctaveButton : OpaqueWidget {
- Octave *module;
+struct OctaveButton : Widget {
int octave;
void draw(const DrawArgs &args) override {
Vec c = box.size.div(2);
- if ((module && module->octave == octave) || octave == 0) {
+ int activeOctave = 0;
+ ParamWidget *paramWidget = getAncestorOfType();
+ if (paramWidget && paramWidget->paramQuantity) {
+ activeOctave = std::round(paramWidget->paramQuantity->getValue());
+ }
+
+ if (activeOctave == octave) {
// Enabled
nvgBeginPath(args.vg);
nvgCircle(args.vg, c.x, c.y, mm2px(4.0/2));
@@ -95,34 +93,20 @@ struct OctaveButton : OpaqueWidget {
}
}
- void onButton(const event::Button &e) override {
- if (e.button == GLFW_MOUSE_BUTTON_RIGHT && e.action == GLFW_PRESS) {
- module->octave = 0;
+ void onDragHover(const event::DragHover &e) override {
+ if (e.button == GLFW_MOUSE_BUTTON_LEFT) {
e.consume(this);
- return;
}
- OpaqueWidget::onButton(e);
+ Widget::onDragHover(e);
}
- void onDragEnter(const event::DragEnter &e) override {
- if (e.button == GLFW_MOUSE_BUTTON_LEFT) {
- OctaveButton *w = dynamic_cast(e.origin);
- if (w) {
- module->octave = octave;
- }
- }
- }
+ void onDragEnter(const event::DragEnter &e) override;
};
-struct OctaveDisplay : OpaqueWidget {
- OctaveDisplay() {
- box.size = mm2px(Vec(15.240, 72.000));
- }
-
- void setModule(Octave *module) {
- clearChildren();
-
+struct OctaveParam : ParamWidget {
+ OctaveParam() {
+ box.size = mm2px(Vec(15.24, 63.0));
const int octaves = 9;
const float margin = mm2px(2.0);
float height = box.size.y - 2*margin;
@@ -130,7 +114,6 @@ struct OctaveDisplay : OpaqueWidget {
OctaveButton *octaveButton = new OctaveButton();
octaveButton->box.pos = Vec(0, height / octaves * i + margin);
octaveButton->box.size = Vec(box.size.x, height / octaves);
- octaveButton->module = module;
octaveButton->octave = 4 - i;
addChild(octaveButton);
}
@@ -143,29 +126,40 @@ struct OctaveDisplay : OpaqueWidget {
nvgFillColor(args.vg, nvgRGB(0, 0, 0));
nvgFill(args.vg);
- Widget::draw(args);
+ ParamWidget::draw(args);
}
};
+inline void OctaveButton::onDragEnter(const event::DragEnter &e) {
+ if (e.button == GLFW_MOUSE_BUTTON_LEFT) {
+ OctaveParam *origin = dynamic_cast(e.origin);
+ if (origin) {
+ ParamWidget *paramWidget = getAncestorOfType();
+ if (paramWidget && paramWidget->paramQuantity) {
+ paramWidget->paramQuantity->setValue(octave);
+ }
+ }
+ }
+ Widget::onDragEnter(e);
+}
+
+
+
struct OctaveWidget : ModuleWidget {
OctaveWidget(Octave *module) {
setModule(module);
setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Octave.svg")));
addChild(createWidget(Vec(RACK_GRID_WIDTH, 0)));
- addChild(createWidget(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
addChild(createWidget(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
- addChild(createWidget(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
- addInput(createInputCentered(mm2px(Vec(7.62, 97.253)), module, Octave::CV_INPUT));
+ addInput(createInputCentered(mm2px(Vec(7.62, 82.753)), module, Octave::OCTAVE_INPUT));
+ addInput(createInputCentered(mm2px(Vec(7.62, 97.253)), module, Octave::PITCH_INPUT));
- addOutput(createOutputCentered(mm2px(Vec(7.62, 112.253)), module, Octave::CV_OUTPUT));
+ addOutput(createOutputCentered(mm2px(Vec(7.62, 112.253)), module, Octave::PITCH_OUTPUT));
- OctaveDisplay *octaveDisplay = new OctaveDisplay();
- octaveDisplay->box.pos = mm2px(Vec(0.0, 14.584));
- octaveDisplay->setModule(module);
- addChild(octaveDisplay);
+ addParam(createParam(mm2px(Vec(0.0, 12.817)), module, Octave::OCTAVE_PARAM));
}
};