Browse Source

Migrate Marbles from AudibleInstrumentsPreview

tags/v1.0.1
Andrew Belt 6 years ago
parent
commit
913bb7ba4b
6 changed files with 3160 additions and 2 deletions
  1. +4
    -0
      CHANGELOG.md
  2. +13
    -2
      Makefile
  3. +2474
    -0
      res/Marbles.svg
  4. +1
    -0
      src/AudibleInstruments.cpp
  5. +1
    -0
      src/AudibleInstruments.hpp
  6. +667
    -0
      src/Marbles.cpp

+ 4
- 0
CHANGELOG.md View File

@@ -1,4 +1,8 @@


### 0.6.2 (2018-10-09)

- Added Random Sampler from Audible Instruments Preview

### 0.6.1 (2018-09-12) ### 0.6.1 (2018-09-12)


- Added Macro Oscillator 2 from Audible Instruments Preview - Added Macro Oscillator 2 from Audible Instruments Preview

+ 13
- 2
Makefile View File

@@ -1,5 +1,5 @@
SLUG = AudibleInstruments SLUG = AudibleInstruments
VERSION = 0.6.1
VERSION = 0.6.2


FLAGS += \ FLAGS += \
-DTEST \ -DTEST \
@@ -76,9 +76,20 @@ SOURCES += eurorack/peaks/number_station/number_station.cc


SOURCES += eurorack/stages/segment_generator.cc SOURCES += eurorack/stages/segment_generator.cc
SOURCES += eurorack/stages/ramp_extractor.cc SOURCES += eurorack/stages/ramp_extractor.cc
# SOURCES += eurorack/stages/chain_state.cc
SOURCES += eurorack/stages/resources.cc SOURCES += eurorack/stages/resources.cc


SOURCES += eurorack/stmlib/utils/random.cc
SOURCES += eurorack/stmlib/dsp/atan.cc
SOURCES += eurorack/stmlib/dsp/units.cc
SOURCES += eurorack/marbles/random/t_generator.cc
SOURCES += eurorack/marbles/random/x_y_generator.cc
SOURCES += eurorack/marbles/random/output_channel.cc
SOURCES += eurorack/marbles/random/lag_processor.cc
SOURCES += eurorack/marbles/random/quantizer.cc
SOURCES += eurorack/marbles/ramp/ramp_extractor.cc
SOURCES += eurorack/marbles/resources.cc


DISTRIBUTABLES += $(wildcard LICENSE*) res DISTRIBUTABLES += $(wildcard LICENSE*) res


RACK_DIR ?= ../.. RACK_DIR ?= ../..


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


+ 1
- 0
src/AudibleInstruments.cpp View File

@@ -24,4 +24,5 @@ void init(rack::Plugin *p) {
p->addModel(modelFrames); p->addModel(modelFrames);
// p->addModel(modelPeaks); // p->addModel(modelPeaks);
// p->addModel(modelStages); // p->addModel(modelStages);
p->addModel(modelMarbles);
} }

+ 1
- 0
src/AudibleInstruments.hpp View File

@@ -22,3 +22,4 @@ extern Model *modelVeils;
extern Model *modelFrames; extern Model *modelFrames;
extern Model *modelPeaks; extern Model *modelPeaks;
extern Model *modelStages; extern Model *modelStages;
extern Model *modelMarbles;

+ 667
- 0
src/Marbles.cpp View File

@@ -0,0 +1,667 @@
#include "AudibleInstruments.hpp"
#include "dsp/digital.hpp"
#include "marbles/random/random_generator.h"
#include "marbles/random/random_stream.h"
#include "marbles/random/t_generator.h"
#include "marbles/random/x_y_generator.h"
#include "marbles/note_filter.h"


static const int BLOCK_SIZE = 5;


static const marbles::Scale preset_scales[6] = {
// C major
{
1.0f,
12,
{
{ 0.0000f, 255 }, // C
{ 0.0833f, 16 }, // C#
{ 0.1667f, 96 }, // D
{ 0.2500f, 24 }, // D#
{ 0.3333f, 128 }, // E
{ 0.4167f, 64 }, // F
{ 0.5000f, 8 }, // F#
{ 0.5833f, 192 }, // G
{ 0.6667f, 16 }, // G#
{ 0.7500f, 96 }, // A
{ 0.8333f, 24 }, // A#
{ 0.9167f, 128 }, // B
}
},

// C minor
{
1.0f,
12,
{
{ 0.0000f, 255 }, // C
{ 0.0833f, 16 }, // C#
{ 0.1667f, 96 }, // D
{ 0.2500f, 128 }, // Eb
{ 0.3333f, 8 }, // E
{ 0.4167f, 64 }, // F
{ 0.5000f, 4 }, // F#
{ 0.5833f, 192 }, // G
{ 0.6667f, 16 }, // G#
{ 0.7500f, 96 }, // A
{ 0.8333f, 128 }, // Bb
{ 0.9167f, 16 }, // B
}
},

// Pentatonic
{
1.0f,
12,
{
{ 0.0000f, 255 }, // C
{ 0.0833f, 4 }, // C#
{ 0.1667f, 96 }, // D
{ 0.2500f, 4 }, // Eb
{ 0.3333f, 4 }, // E
{ 0.4167f, 140 }, // F
{ 0.5000f, 4 }, // F#
{ 0.5833f, 192 }, // G
{ 0.6667f, 4 }, // G#
{ 0.7500f, 96 }, // A
{ 0.8333f, 4 }, // Bb
{ 0.9167f, 4 }, // B
}
},

// Pelog
{
1.0f,
7,
{
{ 0.0000f, 255 }, // C
{ 0.1275f, 128 }, // Db+
{ 0.2625f, 32 }, // Eb-
{ 0.4600f, 8 }, // F#-
{ 0.5883f, 192 }, // G
{ 0.7067f, 64 }, // Ab
{ 0.8817f, 16 }, // Bb+
}
},

// Raag Bhairav That
{
1.0f,
12,
{
{ 0.0000f, 255 }, // ** Sa
{ 0.0752f, 128 }, // ** Komal Re
{ 0.1699f, 4 }, // Re
{ 0.2630f, 4 }, // Komal Ga
{ 0.3219f, 128 }, // ** Ga
{ 0.4150f, 64 }, // ** Ma
{ 0.4918f, 4 }, // Tivre Ma
{ 0.5850f, 192 }, // ** Pa
{ 0.6601f, 64 }, // ** Komal Dha
{ 0.7549f, 4 }, // Dha
{ 0.8479f, 4 }, // Komal Ni
{ 0.9069f, 64 }, // ** Ni
}
},

// Raag Shri
{
1.0f,
12,
{
{ 0.0000f, 255 }, // ** Sa
{ 0.0752f, 4 }, // Komal Re
{ 0.1699f, 128 }, // ** Re
{ 0.2630f, 64 }, // ** Komal Ga
{ 0.3219f, 4 }, // Ga
{ 0.4150f, 128 }, // ** Ma
{ 0.4918f, 4 }, // Tivre Ma
{ 0.5850f, 192 }, // ** Pa
{ 0.6601f, 4 }, // Komal Dha
{ 0.7549f, 64 }, // ** Dha
{ 0.8479f, 128 }, // ** Komal Ni
{ 0.9069f, 4 }, // Ni
}
},
};


struct Marbles : Module {
enum ParamIds {
T_DEJA_VU_PARAM,
X_DEJA_VU_PARAM,
DEJA_VU_PARAM,
T_RATE_PARAM,
X_SPREAD_PARAM,
T_MODE_PARAM,
X_MODE_PARAM,
DEJA_VU_LENGTH_PARAM,
T_BIAS_PARAM,
X_BIAS_PARAM,
T_RANGE_PARAM,
X_RANGE_PARAM,
EXTERNAL_PARAM,
T_JITTER_PARAM,
X_STEPS_PARAM,
NUM_PARAMS
};
enum InputIds {
T_BIAS_INPUT,
X_BIAS_INPUT,
T_CLOCK_INPUT,
T_RATE_INPUT,
T_JITTER_INPUT,
DEJA_VU_INPUT,
X_STEPS_INPUT,
X_SPREAD_INPUT,
X_CLOCK_INPUT,
NUM_INPUTS
};
enum OutputIds {
T1_OUTPUT,
T2_OUTPUT,
T3_OUTPUT,
Y_OUTPUT,
X1_OUTPUT,
X2_OUTPUT,
X3_OUTPUT,
NUM_OUTPUTS
};
enum LightIds {
T_DEJA_VU_LIGHT,
X_DEJA_VU_LIGHT,
ENUMS(T_MODE_LIGHTS, 2),
ENUMS(X_MODE_LIGHTS, 2),
ENUMS(T_RANGE_LIGHTS, 2),
ENUMS(X_RANGE_LIGHTS, 2),
EXTERNAL_LIGHT,
T1_LIGHT,
T2_LIGHT,
T3_LIGHT,
Y_LIGHT,
X1_LIGHT,
X2_LIGHT,
X3_LIGHT,
NUM_LIGHTS
};

marbles::RandomGenerator random_generator;
marbles::RandomStream random_stream;
marbles::TGenerator t_generator;
marbles::XYGenerator xy_generator;
marbles::NoteFilter note_filter;

// State
BooleanTrigger tDejaVuTrigger;
BooleanTrigger xDejaVuTrigger;
BooleanTrigger tModeTrigger;
BooleanTrigger xModeTrigger;
BooleanTrigger tRangeTrigger;
BooleanTrigger xRangeTrigger;
BooleanTrigger externalTrigger;
bool t_deja_vu;
bool x_deja_vu;
int t_mode;
int x_mode;
int t_range;
int x_range;
bool external;
int x_scale;
int y_divider_index;
int x_clock_source_internal;

// Buffers
stmlib::GateFlags t_clocks[BLOCK_SIZE] = {};
stmlib::GateFlags last_t_clock = 0;
stmlib::GateFlags xy_clocks[BLOCK_SIZE] = {};
stmlib::GateFlags last_xy_clock = 0;
float ramp_master[BLOCK_SIZE] = {};
float ramp_external[BLOCK_SIZE] = {};
float ramp_slave[2][BLOCK_SIZE] = {};
bool gates[BLOCK_SIZE * 2] = {};
float voltages[BLOCK_SIZE * 4] = {};
int blockIndex = 0;

Marbles() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {
random_generator.Init(1);
random_stream.Init(&random_generator);
note_filter.Init();
onSampleRateChange();
onReset();
}

void onReset() override {
t_deja_vu = false;
x_deja_vu = false;
t_mode = 0;
x_mode = 0;
t_range = 1;
x_range = 1;
external = false;
x_scale = 0;
y_divider_index = 8;
x_clock_source_internal = 0;
}

void onRandomize() override {
t_mode = randomu32() % 3;
x_mode = randomu32() % 3;
t_range = randomu32() % 3;
x_range = randomu32() % 3;
}

void onSampleRateChange() override {
float sampleRate = engineGetSampleRate();
t_generator.Init(&random_stream, sampleRate);
xy_generator.Init(&random_stream, sampleRate);

// Set scales
for (int i = 0; i < 6; i++) {
xy_generator.LoadScale(i, preset_scales[i]);
}
}

json_t *toJson() override {
json_t *rootJ = json_object();

json_object_set_new(rootJ, "t_deja_vu", json_boolean(t_deja_vu));
json_object_set_new(rootJ, "x_deja_vu", json_boolean(x_deja_vu));
json_object_set_new(rootJ, "t_mode", json_integer(t_mode));
json_object_set_new(rootJ, "x_mode", json_integer(x_mode));
json_object_set_new(rootJ, "t_range", json_integer(t_range));
json_object_set_new(rootJ, "x_range", json_integer(x_range));
json_object_set_new(rootJ, "external", json_boolean(external));
json_object_set_new(rootJ, "x_scale", json_integer(x_scale));
json_object_set_new(rootJ, "y_divider_index", json_integer(y_divider_index));
json_object_set_new(rootJ, "x_clock_source_internal", json_integer(x_clock_source_internal));

return rootJ;
}

void fromJson(json_t *rootJ) override {
json_t *t_deja_vuJ = json_object_get(rootJ, "t_deja_vu");
if (t_deja_vuJ)
t_deja_vu = json_boolean_value(t_deja_vuJ);

json_t *x_deja_vuJ = json_object_get(rootJ, "x_deja_vu");
if (x_deja_vuJ)
x_deja_vu = json_boolean_value(x_deja_vuJ);

json_t *t_modeJ = json_object_get(rootJ, "t_mode");
if (t_modeJ)
t_mode = json_integer_value(t_modeJ);

json_t *x_modeJ = json_object_get(rootJ, "x_mode");
if (x_modeJ)
x_mode = json_integer_value(x_modeJ);

json_t *t_rangeJ = json_object_get(rootJ, "t_range");
if (t_rangeJ)
t_range = json_integer_value(t_rangeJ);

json_t *x_rangeJ = json_object_get(rootJ, "x_range");
if (x_rangeJ)
x_range = json_integer_value(x_rangeJ);

json_t *externalJ = json_object_get(rootJ, "external");
if (externalJ)
external = json_boolean_value(externalJ);

json_t *x_scaleJ = json_object_get(rootJ, "x_scale");
if (x_scaleJ)
x_scale = json_integer_value(x_scaleJ);

json_t *y_divider_indexJ = json_object_get(rootJ, "y_divider_index");
if (y_divider_indexJ)
y_divider_index = json_integer_value(y_divider_indexJ);

json_t *x_clock_source_internalJ = json_object_get(rootJ, "x_clock_source_internal");
if (x_clock_source_internalJ)
x_clock_source_internal = json_integer_value(x_clock_source_internalJ);
}

void step() override {
// Buttons
if (tDejaVuTrigger.process(params[T_DEJA_VU_PARAM].value <= 0.f)) {
t_deja_vu = !t_deja_vu;
}
if (xDejaVuTrigger.process(params[X_DEJA_VU_PARAM].value <= 0.f)) {
x_deja_vu = !x_deja_vu;
}
if (tModeTrigger.process(params[T_MODE_PARAM].value <= 0.f)) {
t_mode = (t_mode + 1) % 3;
}
if (xModeTrigger.process(params[X_MODE_PARAM].value <= 0.f)) {
x_mode = (x_mode + 1) % 3;
}
if (tRangeTrigger.process(params[T_RANGE_PARAM].value <= 0.f)) {
t_range = (t_range + 1) % 3;
}
if (xRangeTrigger.process(params[X_RANGE_PARAM].value <= 0.f)) {
x_range = (x_range + 1) % 3;
}
if (externalTrigger.process(params[EXTERNAL_PARAM].value <= 0.f)) {
external = !external;
}

// Clocks
bool t_gate = (inputs[T_CLOCK_INPUT].value >= 1.7f);
last_t_clock = stmlib::ExtractGateFlags(last_t_clock, t_gate);
t_clocks[blockIndex] = last_t_clock;

bool x_gate = (inputs[X_CLOCK_INPUT].value >= 1.7f);
last_xy_clock = stmlib::ExtractGateFlags(last_xy_clock, x_gate);
xy_clocks[blockIndex] = last_xy_clock;

// Process block
if (++blockIndex >= BLOCK_SIZE) {
blockIndex = 0;
stepBlock();
}

// Lights and outputs

lights[T_DEJA_VU_LIGHT].setBrightness(t_deja_vu);
lights[X_DEJA_VU_LIGHT].setBrightness(x_deja_vu);

lights[T_MODE_LIGHTS + 0].setBrightness(t_mode == 0 || t_mode == 1);
lights[T_MODE_LIGHTS + 1].setBrightness(t_mode == 1 || t_mode == 2);

lights[X_MODE_LIGHTS + 0].setBrightness(x_mode == 0 || x_mode == 1);
lights[X_MODE_LIGHTS + 1].setBrightness(x_mode == 1 || x_mode == 2);

lights[T_RANGE_LIGHTS + 0].setBrightness(t_range == 0 || t_range == 1);
lights[T_RANGE_LIGHTS + 1].setBrightness(t_range == 1 || t_range == 2);

lights[X_RANGE_LIGHTS + 0].setBrightness(x_range == 0 || x_range == 1);
lights[X_RANGE_LIGHTS + 1].setBrightness(x_range == 1 || x_range == 2);

lights[EXTERNAL_LIGHT].setBrightness(external);

outputs[T1_OUTPUT].value = gates[blockIndex*2 + 0] ? 10.f : 0.f;
lights[T1_LIGHT].setBrightnessSmooth(gates[blockIndex*2 + 0]);
outputs[T2_OUTPUT].value = (ramp_master[blockIndex] < 0.5f) ? 10.f : 0.f;
lights[T2_LIGHT].setBrightnessSmooth(ramp_master[blockIndex] < 0.5f);
outputs[T3_OUTPUT].value = gates[blockIndex*2 + 1] ? 10.f : 0.f;
lights[T3_LIGHT].setBrightnessSmooth(gates[blockIndex*2 + 1]);

outputs[X1_OUTPUT].value = voltages[blockIndex*4 + 0];
lights[X1_LIGHT].setBrightnessSmooth(voltages[blockIndex*4 + 0]);
outputs[X2_OUTPUT].value = voltages[blockIndex*4 + 1];
lights[X2_LIGHT].setBrightnessSmooth(voltages[blockIndex*4 + 1]);
outputs[X3_OUTPUT].value = voltages[blockIndex*4 + 2];
lights[X3_LIGHT].setBrightnessSmooth(voltages[blockIndex*4 + 2]);
outputs[Y_OUTPUT].value = voltages[blockIndex*4 + 3];
lights[Y_LIGHT].setBrightnessSmooth(voltages[blockIndex*4 + 3]);
}

void stepBlock() {
// Ramps

marbles::Ramps ramps;
ramps.master = ramp_master;
ramps.external = ramp_external;
ramps.slave[0] = ramp_slave[0];
ramps.slave[1] = ramp_slave[1];

float deja_vu = clamp(params[DEJA_VU_PARAM].value + inputs[DEJA_VU_INPUT].value / 5.f, 0.f, 1.f);
static const int loop_length[] = {
1, 1, 1, 2, 2,
2, 2, 2, 3, 3,
3, 3, 4, 4, 4,
4, 4, 5, 5, 6,
6, 6, 7, 7, 8,
8, 8, 10, 10, 12,
12, 12, 14, 14, 16,
16
};
float deja_vu_length_index = params[DEJA_VU_LENGTH_PARAM].value * (LENGTHOF(loop_length) - 1);
int deja_vu_length = loop_length[(int) roundf(deja_vu_length_index)];

// Set up TGenerator

bool t_external_clock = inputs[T_CLOCK_INPUT].active;

t_generator.set_model((marbles::TGeneratorModel) t_mode);
t_generator.set_range((marbles::TGeneratorRange) t_range);
float t_rate = 60.f * (params[T_RATE_PARAM].value + inputs[T_RATE_INPUT].value / 5.f);
t_generator.set_rate(t_rate);
float t_bias = clamp(params[T_BIAS_PARAM].value + inputs[T_BIAS_INPUT].value / 5.f, 0.f, 1.f);
t_generator.set_bias(t_bias);
float t_jitter = clamp(params[T_JITTER_PARAM].value + inputs[T_JITTER_INPUT].value / 5.f, 0.f, 1.f);
t_generator.set_jitter(t_jitter);
t_generator.set_deja_vu(t_deja_vu ? deja_vu : 0.f);
t_generator.set_length(deja_vu_length);
// TODO
t_generator.set_pulse_width_mean(0.f);
t_generator.set_pulse_width_std(0.f);

t_generator.Process(t_external_clock, t_clocks, ramps, gates, BLOCK_SIZE);

// Set up XYGenerator

marbles::ClockSource x_clock_source = (marbles::ClockSource) x_clock_source_internal;
if (inputs[X_CLOCK_INPUT].active)
x_clock_source = marbles::CLOCK_SOURCE_EXTERNAL;

marbles::GroupSettings x;
x.control_mode = (marbles::ControlMode) x_mode;
x.voltage_range = (marbles::VoltageRange) x_range;
// TODO Fix the scaling
float note_cv = 0.5f * (params[X_SPREAD_PARAM].value + inputs[X_SPREAD_INPUT].value / 5.f);
float u = note_filter.Process(0.5f * (note_cv + 1.f));
x.register_mode = external;
x.register_value = u;

float x_spread = clamp(params[X_SPREAD_PARAM].value + inputs[X_SPREAD_INPUT].value / 5.f, 0.f, 1.f);
x.spread = x_spread;
float x_bias = clamp(params[X_BIAS_PARAM].value + inputs[X_BIAS_INPUT].value / 5.f, 0.f, 1.f);
x.bias = x_bias;
float x_steps = clamp(params[X_STEPS_PARAM].value + inputs[X_STEPS_INPUT].value / 5.f, 0.f, 1.f);
x.steps = x_steps;
x.deja_vu = x_deja_vu ? deja_vu : 0.f;
x.length = deja_vu_length;
x.ratio.p = 1;
x.ratio.q = 1;
x.scale_index = x_scale;

marbles::GroupSettings y;
y.control_mode = marbles::CONTROL_MODE_IDENTICAL;
// TODO
y.voltage_range = (marbles::VoltageRange) x_range;
y.register_mode = false;
y.register_value = 0.0f;
// TODO
y.spread = x_spread;
y.bias = x_bias;
y.steps = x_steps;
y.deja_vu = 0.0f;
y.length = 1;
static const marbles::Ratio y_divider_ratios[] = {
{ 1, 64 },
{ 1, 48 },
{ 1, 32 },
{ 1, 24 },
{ 1, 16 },
{ 1, 12 },
{ 1, 8 },
{ 1, 6 },
{ 1, 4 },
{ 1, 3 },
{ 1, 2 },
{ 1, 1 },
};
y.ratio = y_divider_ratios[y_divider_index];
y.scale_index = x_scale;

xy_generator.Process(x_clock_source, x, y, xy_clocks, ramps, voltages, BLOCK_SIZE);
}
};


template <typename BASE>
struct CKD6Light : BASE {
CKD6Light() {
this->box.size = Vec(22, 22);
}
};


struct MarblesWidget : ModuleWidget {
MarblesWidget(Marbles *module) : ModuleWidget(module) {
setPanel(SVG::load(assetPlugin(plugin, "res/Marbles.svg")));

addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, 0)));
addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
addChild(createWidget<ScrewSilver>(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
addChild(createWidget<ScrewSilver>(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));

addParam(createParamCentered<CKD6>(mm2px(Vec(16.545, 17.794)), module, Marbles::T_DEJA_VU_PARAM, 0.0, 1.0, 0.0));
addParam(createParamCentered<CKD6>(mm2px(Vec(74.845, 17.794)), module, Marbles::X_DEJA_VU_PARAM, 0.0, 1.0, 0.0));
addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(45.695, 22.244)), module, Marbles::DEJA_VU_PARAM, 0.0, 1.0, 0.5));
addParam(createParamCentered<Rogan3PSWhite>(mm2px(Vec(23.467, 35.264)), module, Marbles::T_RATE_PARAM, -1.0, 1.0, 0.0));
addParam(createParamCentered<Rogan3PSWhite>(mm2px(Vec(67.945, 35.243)), module, Marbles::X_SPREAD_PARAM, 0.0, 1.0, 0.5));
addParam(createParamCentered<TL1105>(mm2px(Vec(6.945, 38.794)), module, Marbles::T_MODE_PARAM, 0.0, 1.0, 0.0));
addParam(createParamCentered<TL1105>(mm2px(Vec(84.445, 38.793)), module, Marbles::X_MODE_PARAM, 0.0, 1.0, 0.0));
addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(45.695, 51.144)), module, Marbles::DEJA_VU_LENGTH_PARAM, 0.0, 1.0, 0.0));
addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(9.545, 58.394)), module, Marbles::T_BIAS_PARAM, 0.0, 1.0, 0.5));
addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(81.844, 58.394)), module, Marbles::X_BIAS_PARAM, 0.0, 1.0, 0.5));
addParam(createParamCentered<TL1105>(mm2px(Vec(26.644, 59.694)), module, Marbles::T_RANGE_PARAM, 0.0, 1.0, 0.0));
addParam(createParamCentered<TL1105>(mm2px(Vec(64.744, 59.694)), module, Marbles::X_RANGE_PARAM, 0.0, 1.0, 0.0));
addParam(createParamCentered<TL1105>(mm2px(Vec(45.694, 67.294)), module, Marbles::EXTERNAL_PARAM, 0.0, 1.0, 0.0));
addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(31.544, 73.694)), module, Marbles::T_JITTER_PARAM, 0.0, 1.0, 0.0));
addParam(createParamCentered<Rogan2PSWhite>(mm2px(Vec(59.845, 73.694)), module, Marbles::X_STEPS_PARAM, 0.0, 1.0, 0.5));

addInput(createInputCentered<PJ301MPort>(mm2px(Vec(9.545, 81.944)), module, Marbles::T_BIAS_INPUT));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(81.844, 81.944)), module, Marbles::X_BIAS_INPUT));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(9.545, 96.544)), module, Marbles::T_CLOCK_INPUT));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(21.595, 96.544)), module, Marbles::T_RATE_INPUT));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(33.644, 96.544)), module, Marbles::T_JITTER_INPUT));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(45.695, 96.544)), module, Marbles::DEJA_VU_INPUT));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(57.745, 96.544)), module, Marbles::X_STEPS_INPUT));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(69.795, 96.544)), module, Marbles::X_SPREAD_INPUT));
addInput(createInputCentered<PJ301MPort>(mm2px(Vec(81.844, 96.544)), module, Marbles::X_CLOCK_INPUT));

addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(9.545, 111.144)), module, Marbles::T1_OUTPUT));
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(21.595, 111.144)), module, Marbles::T2_OUTPUT));
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(33.644, 111.144)), module, Marbles::T3_OUTPUT));
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(45.695, 111.144)), module, Marbles::Y_OUTPUT));
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(57.745, 111.144)), module, Marbles::X1_OUTPUT));
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(69.795, 111.144)), module, Marbles::X2_OUTPUT));
addOutput(createOutputCentered<PJ301MPort>(mm2px(Vec(81.844, 111.144)), module, Marbles::X3_OUTPUT));

addChild(createLightCentered<CKD6Light<GreenLight>>(mm2px(Vec(16.545, 17.794)), module, Marbles::T_DEJA_VU_LIGHT));
addChild(createLightCentered<CKD6Light<GreenLight>>(mm2px(Vec(74.845, 17.794)), module, Marbles::X_DEJA_VU_LIGHT));
addChild(createLightCentered<MediumLight<GreenRedLight>>(mm2px(Vec(6.944, 29.894)), module, Marbles::T_MODE_LIGHTS));
addChild(createLightCentered<MediumLight<GreenRedLight>>(mm2px(Vec(84.444, 29.894)), module, Marbles::X_MODE_LIGHTS));
addChild(createLightCentered<MediumLight<GreenRedLight>>(mm2px(Vec(26.644, 53.994)), module, Marbles::T_RANGE_LIGHTS));
addChild(createLightCentered<MediumLight<GreenRedLight>>(mm2px(Vec(64.744, 53.994)), module, Marbles::X_RANGE_LIGHTS));
addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(45.695, 76.194)), module, Marbles::EXTERNAL_LIGHT));
addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(6.044, 104.794)), module, Marbles::T1_LIGHT));
addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(18.094, 104.794)), module, Marbles::T2_LIGHT));
addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(30.145, 104.794)), module, Marbles::T3_LIGHT));
addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(42.194, 104.794)), module, Marbles::Y_LIGHT));
addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(54.244, 104.794)), module, Marbles::X1_LIGHT));
addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(66.294, 104.794)), module, Marbles::X2_LIGHT));
addChild(createLightCentered<MediumLight<GreenLight>>(mm2px(Vec(78.344, 104.794)), module, Marbles::X3_LIGHT));
}

void appendContextMenu(Menu *menu) override {
Marbles *module = dynamic_cast<Marbles*>(this->module);

struct ScaleItem : MenuItem {
Marbles *module;
int scale;
void onAction(EventAction &e) override {
module->x_scale = scale;
}
};

menu->addChild(MenuEntry::create());
menu->addChild(MenuLabel::create("Scales"));
const std::string scaleLabels[] = {
"Major",
"Minor",
"Pentatonic",
"Pelog",
"Raag Bhairav That",
"Raag Shri",
};
for (int i = 0; i < (int) LENGTHOF(scaleLabels); i++) {
ScaleItem *item = MenuItem::create<ScaleItem>(scaleLabels[i], CHECKMARK(module->x_scale == i));
item->module = module;
item->scale = i;
menu->addChild(item);
}

struct XClockSourceInternal : MenuItem {
Marbles *module;
int source;
void onAction(EventAction &e) override {
module->x_clock_source_internal = source;
}
};

menu->addChild(MenuEntry::create());
menu->addChild(MenuLabel::create("Internal X clock source"));
const std::string sourceLabels[] = {
"T₁ → X₁, T₂ → X₂, T₃ → X₃",
"T₁ → X₁, X₂, X₃",
"T₂ → X₁, X₂, X₃",
"T₃ → X₁, X₂, X₃",
};
for (int i = 0; i < (int) LENGTHOF(sourceLabels); i++) {
XClockSourceInternal *item = MenuItem::create<XClockSourceInternal>(sourceLabels[i], CHECKMARK(module->x_clock_source_internal == i));
item->module = module;
item->source = i;
menu->addChild(item);
}

struct YDividerIndexItem : MenuItem {
Marbles *module;
int index;
void onAction(EventAction &e) override {
module->y_divider_index = index;
}
};

struct YDividerItem : MenuItem {
Marbles *module;
Menu *createChildMenu() override {
Menu *menu = new Menu();
const std::string yDividerRatioLabels[] = {
"1/64",
"1/48",
"1/32",
"1/24",
"1/16",
"1/12",
"1/8",
"1/6",
"1/4",
"1/3",
"1/2",
"1",
};
for (int i = 0; i < (int) LENGTHOF(yDividerRatioLabels); i++) {
YDividerIndexItem *item = MenuItem::create<YDividerIndexItem>(yDividerRatioLabels[i], CHECKMARK(module->y_divider_index == i));
item->module = module;
item->index = i;
menu->addChild(item);
}
return menu;
}
};

menu->addChild(MenuEntry::create());
YDividerItem *yDividerItem = MenuItem::create<YDividerItem>("Y divider ratio");
yDividerItem->module = module;
menu->addChild(yDividerItem);
}
};


Model *modelMarbles = createModel<Marbles, MarblesWidget>("Audible Instruments", "Marbles", "Random Sampler");


Loading…
Cancel
Save