Browse Source

Rewrite and re-panel Branches. Make Branches polyphonic.

tags/v1.4.0
Andrew Belt 4 years ago
parent
commit
44c516c29b
4 changed files with 618 additions and 862 deletions
  1. +4
    -0
      CHANGELOG.md
  2. +3
    -2
      plugin.json
  3. +512
    -779
      res/Branches.svg
  4. +99
    -81
      src/Branches.cpp

+ 4
- 0
CHANGELOG.md View File

@@ -1,3 +1,7 @@
### 1.3.1 (2020-07-14)
- Rewrite and re-panel Branches.
- Make Branches polyphonic.

### 1.3.0 (2020-05-29) ### 1.3.0 (2020-05-29)
- Add EQ Filter. - Add EQ Filter.




+ 3
- 2
plugin.json View File

@@ -1,6 +1,6 @@
{ {
"slug": "AudibleInstruments", "slug": "AudibleInstruments",
"version": "1.3.0",
"version": "1.3.1",
"license": "GPL-3.0-or-later", "license": "GPL-3.0-or-later",
"name": "Audible Instruments", "name": "Audible Instruments",
"author": "VCV", "author": "VCV",
@@ -155,7 +155,8 @@
"tags": [ "tags": [
"Random", "Random",
"Dual", "Dual",
"Hardware clone"
"Hardware clone",
"Polyphonic"
] ]
}, },
{ {


+ 512
- 779
res/Branches.svg
File diff suppressed because it is too large
View File


+ 99
- 81
src/Branches.cpp View File

@@ -24,24 +24,87 @@ struct Branches : Module {
NUM_OUTPUTS NUM_OUTPUTS
}; };
enum LightIds { enum LightIds {
MODE1_LIGHT,
MODE2_LIGHT,
STATE1_POS_LIGHT, STATE1_NEG_LIGHT,
STATE2_POS_LIGHT, STATE2_NEG_LIGHT,
ENUMS(STATE_LIGHTS, 2 * 2),
NUM_LIGHTS NUM_LIGHTS
}; };


dsp::SchmittTrigger gateTriggers[2];
dsp::SchmittTrigger modeTriggers[2];
dsp::BooleanTrigger gateTriggers[2][16];
dsp::BooleanTrigger modeTriggers[2];
bool modes[2] = {}; bool modes[2] = {};
bool outcomes[2] = {};
bool outcomes[2][16] = {};


Branches() { Branches() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
configParam(THRESHOLD1_PARAM, 0.0, 1.0, 0.5, "Probability 1");
configParam(MODE1_PARAM, 0.0, 1.0, 0.0, "Mode 1");
configParam(THRESHOLD2_PARAM, 0.0, 1.0, 0.5, "Probability 2");
configParam(MODE2_PARAM, 0.0, 1.0, 0.0, "Mode 2");
configParam(THRESHOLD1_PARAM, 0.0, 1.0, 0.5, "Channel 1 probability", "%", 0, 100);
configParam(MODE1_PARAM, 0.0, 1.0, 0.0, "Channel 1 mode");
configParam(THRESHOLD2_PARAM, 0.0, 1.0, 0.5, "Channel 2 probability", "%", 0, 100);
configParam(MODE2_PARAM, 0.0, 1.0, 0.0, "Channel 2 mode");
}

void process(const ProcessArgs& args) override {
for (int i = 0; i < 2; i++) {
// Get input
Input* input = &inputs[IN1_INPUT + i];
// 2nd input is normalized to 1st.
if (i == 1 && !input->isConnected())
input = &inputs[IN1_INPUT + 0];
int channels = std::max(input->getChannels(), 1);

// mode button
if (modeTriggers[i].process(params[MODE1_PARAM + i].getValue() > 0.f))
modes[i] ^= true;

bool lightA = false;
bool lightB = false;

// Process triggers
for (int c = 0; c < channels; c++) {
bool gate = input->getVoltage(c) >= 2.f;
if (gateTriggers[i][c].process(gate)) {
// trigger
// We don't have to clamp here because the threshold comparison works without it.
float threshold = params[THRESHOLD1_PARAM + i].getValue() + inputs[P1_INPUT + i].getPolyVoltage(c) / 10.f;
bool toss = (random::uniform() < threshold);
if (!modes[i]) {
// direct modes
outcomes[i][c] = toss;
}
else {
// toggle modes
if (toss)
outcomes[i][c] ^= true;
}
}

// Output gate logic
bool gateA = !outcomes[i][c] && (modes[i] ? true : gate);
bool gateB = outcomes[i][c] && (modes[i] ? true : gate);

if (gateA)
lightA = true;
if (gateB)
lightB = true;

// Set output gates
outputs[OUT1A_OUTPUT + i].setVoltage(gateA ? 10.f : 0.f, c);
outputs[OUT1B_OUTPUT + i].setVoltage(gateB ? 10.f : 0.f, c);
}

outputs[OUT1A_OUTPUT + i].setChannels(channels);
outputs[OUT1B_OUTPUT + i].setChannels(channels);

lights[STATE_LIGHTS + i * 2 + 1].setSmoothBrightness(lightA, args.sampleTime);
lights[STATE_LIGHTS + i * 2 + 0].setSmoothBrightness(lightB, args.sampleTime);
}
}

void onReset() override {
for (int i = 0; i < 2; i++) {
modes[i] = false;
for (int c = 0; c < 16; c++) {
outcomes[i][c] = false;
}
}
} }


json_t* dataToJson() override { json_t* dataToJson() override {
@@ -64,52 +127,6 @@ struct Branches : Module {
} }
} }
} }

void process(const ProcessArgs& args) override {
float gate = 0.0;
for (int i = 0; i < 2; i++) {
// mode button
if (modeTriggers[i].process(params[MODE1_PARAM + i].getValue()))
modes[i] = !modes[i];

if (inputs[IN1_INPUT + i].isConnected())
gate = inputs[IN1_INPUT + i].getVoltage();

if (gateTriggers[i].process(gate)) {
// trigger
float r = random::uniform();
float threshold = clamp(params[THRESHOLD1_PARAM + i].getValue() + inputs[P1_INPUT + i].getVoltage() / 10.f, 0.f, 1.f);
bool toss = (r < threshold);
if (!modes[i]) {
// direct modes
outcomes[i] = toss;
}
else {
// toggle modes
outcomes[i] = (outcomes[i] != toss);
}

if (!outcomes[i])
lights[STATE1_POS_LIGHT + 2 * i].value = 1.0;
else
lights[STATE1_NEG_LIGHT + 2 * i].value = 1.0;
}

lights[STATE1_POS_LIGHT + 2 * i].value *= 1.0 - args.sampleTime * 15.0;
lights[STATE1_NEG_LIGHT + 2 * i].value *= 1.0 - args.sampleTime * 15.0;
lights[MODE1_LIGHT + i].value = modes[i] ? 1.0 : 0.0;

outputs[OUT1A_OUTPUT + i].setVoltage(outcomes[i] ? 0.0 : gate);
outputs[OUT1B_OUTPUT + i].setVoltage(outcomes[i] ? gate : 0.0);
}
}

void onReset() override {
for (int i = 0; i < 2; i++) {
modes[i] = false;
outcomes[i] = false;
}
}
}; };




@@ -118,25 +135,26 @@ struct BranchesWidget : ModuleWidget {
setModule(module); setModule(module);
setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Branches.svg"))); setPanel(APP->window->loadSvg(asset::plugin(pluginInstance, "res/Branches.svg")));


addChild(createWidget<ScrewSilver>(Vec(15, 0)));
addChild(createWidget<ScrewSilver>(Vec(15, 365)));

addParam(createParam<Rogan1PSRed>(Vec(24, 64), module, Branches::THRESHOLD1_PARAM));
addParam(createParam<TL1105>(Vec(69, 58), module, Branches::MODE1_PARAM));
addInput(createInput<PJ301MPort>(Vec(9, 122), module, Branches::IN1_INPUT));
addInput(createInput<PJ301MPort>(Vec(55, 122), module, Branches::P1_INPUT));
addOutput(createOutput<PJ301MPort>(Vec(9, 160), module, Branches::OUT1A_OUTPUT));
addOutput(createOutput<PJ301MPort>(Vec(55, 160), module, Branches::OUT1B_OUTPUT));

addParam(createParam<Rogan1PSGreen>(Vec(24, 220), module, Branches::THRESHOLD2_PARAM));
addParam(createParam<TL1105>(Vec(69, 214), module, Branches::MODE2_PARAM));
addInput(createInput<PJ301MPort>(Vec(9, 278), module, Branches::IN2_INPUT));
addInput(createInput<PJ301MPort>(Vec(55, 278), module, Branches::P2_INPUT));
addOutput(createOutput<PJ301MPort>(Vec(9, 316), module, Branches::OUT2A_OUTPUT));
addOutput(createOutput<PJ301MPort>(Vec(55, 316), module, Branches::OUT2B_OUTPUT));

addChild(createLight<SmallLight<GreenRedLight>>(Vec(40, 169), module, Branches::STATE1_POS_LIGHT));
addChild(createLight<SmallLight<GreenRedLight>>(Vec(40, 325), module, Branches::STATE2_POS_LIGHT));
addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));

addParam(createParamCentered<TL1105>(mm2px(Vec(25.852, 22.24)), module, Branches::MODE1_PARAM));
addParam(createParamCentered<Rogan1PSRed>(mm2px(Vec(15.057, 28.595)), module, Branches::THRESHOLD1_PARAM));
addParam(createParamCentered<TL1105>(mm2px(Vec(25.852, 74.95)), module, Branches::MODE2_PARAM));
addParam(createParamCentered<Rogan1PSGreen>(mm2px(Vec(15.057, 81.296)), module, Branches::THRESHOLD2_PARAM));

addInput(createInputCentered<PJ301MPort>(mm2px(Vec(7.112, 45.74)), module, Branches::IN1_INPUT));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(22.991, 45.74)), module, Branches::P1_INPUT));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(7.112, 98.44)), module, Branches::IN2_INPUT));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(22.991, 98.44)), module, Branches::P2_INPUT));

addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(7.112, 58.44)), module, Branches::OUT1A_OUTPUT));
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(22.991, 58.44)), module, Branches::OUT1B_OUTPUT));
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(7.112, 111.14)), module, Branches::OUT2A_OUTPUT));
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(22.991, 111.14)), module, Branches::OUT2B_OUTPUT));

addChild(createLightCentered<MediumLight<GreenRedLight>>(mm2px(Vec(15.052, 58.45)), module, Branches::STATE_LIGHTS + 0 * 2));
addChild(createLightCentered<MediumLight<GreenRedLight>>(mm2px(Vec(15.052, 111.151)), module, Branches::STATE_LIGHTS + 1 * 2));
} }


void appendContextMenu(Menu* menu) override { void appendContextMenu(Menu* menu) override {
@@ -145,12 +163,12 @@ struct BranchesWidget : ModuleWidget {


struct BranchesModeItem : MenuItem { struct BranchesModeItem : MenuItem {
Branches* branches; Branches* branches;
int channel;
int i;
void onAction(const event::Action& e) override { void onAction(const event::Action& e) override {
branches->modes[channel] ^= 1;
branches->modes[i] ^= 1;
} }
void step() override { void step() override {
rightText = branches->modes[channel] ? "Toggle" : "Latch";
rightText = branches->modes[i] ? "Latch" : "Toggle";
MenuItem::step(); MenuItem::step();
} }
}; };
@@ -158,8 +176,8 @@ struct BranchesWidget : ModuleWidget {
menu->addChild(new MenuSeparator); menu->addChild(new MenuSeparator);


menu->addChild(construct<MenuLabel>(&MenuLabel::text, "Channels")); menu->addChild(construct<MenuLabel>(&MenuLabel::text, "Channels"));
menu->addChild(construct<BranchesModeItem>(&MenuItem::text, "Channel 1 modes", &BranchesModeItem::branches, branches, &BranchesModeItem::channel, 0));
menu->addChild(construct<BranchesModeItem>(&MenuItem::text, "Channel 2 modes", &BranchesModeItem::branches, branches, &BranchesModeItem::channel, 1));
menu->addChild(construct<BranchesModeItem>(&MenuItem::text, "Channel 1 mode", &BranchesModeItem::branches, branches, &BranchesModeItem::i, 0));
menu->addChild(construct<BranchesModeItem>(&MenuItem::text, "Channel 2 mode", &BranchesModeItem::branches, branches, &BranchesModeItem::i, 1));
} }
}; };




Loading…
Cancel
Save