diff --git a/Makefile b/Makefile
index 18bbdc9..19739b6 100644
--- a/Makefile
+++ b/Makefile
@@ -11,12 +11,13 @@ VERSION = 0.6.2
# FLAGS will be passed to both the C and C++ compiler
#FLAGS += -Idep/openmpt-libopenmpt-0.3.10/soundlib -Idep/openmpt-libopenmpt-0.3.10/common
-CFLAGS +=
-CXXFLAGS +=
+CFLAGS +=
+CXXFLAGS +=
# Careful about linking to shared libraries, since you can't assume much about the user's environment and library search path.
# Static libraries are fine.
#LDFLAGS = -Ldep -Ldep/openmpt-libopenmpt-0.3.10/bin/libopenmpt.a
+LDFLAGS = -Ldep
# Add .cpp and .c files to the build
SOURCES += $(wildcard src/*.cpp) $(wildcard src/*.c)
diff --git a/dep/Makefile b/dep/Makefile
deleted file mode 100644
index 976ba22..0000000
--- a/dep/Makefile
+++ /dev/null
@@ -1,37 +0,0 @@
-RACK_DIR ?= ../../..
-.NOTPARALLEL:
-
-
-# Target paths
-
-include $(RACK_DIR)/arch.mk
-
-ifdef ARCH_LIN
- openmpt = lib/openmpt.a
-endif
-
-ifdef ARCH_MAC
- openmtp = lib/openmpt.a
-endif
-
-ifdef ARCH_WIN
- openmpt = lib/openmpt.a
-endif
-
-nanovg = include/openmpt.h
-
-DEPS += $(openmpt)
-include $(RACK_DIR)/dep.mk
-
-
-# Targets
-
-$(openmpt):
- $(WGET) "https://github.com/OpenMPT/openmpt/archive/libopenmpt-0.3.10.tar.gz"
- $(UNTAR) libopenmpt-0.3.10.tar.gz
- $(MAKE) -C openmpt-libopenmpt-0.3.10
-
-
-clean:
- git clean -fdx
- git submodule foreach git clean -fdx
diff --git a/res/AudioInterface16.svg b/res/AudioInterface16.svg
new file mode 100644
index 0000000..ff11172
--- /dev/null
+++ b/res/AudioInterface16.svg
@@ -0,0 +1,10517 @@
+
+
diff --git a/res/CVMoment.svg b/res/CVMoment.svg
new file mode 100644
index 0000000..e89246e
--- /dev/null
+++ b/res/CVMoment.svg
@@ -0,0 +1,4894 @@
+
+
+
+
diff --git a/res/CVSlider0to10.svg b/res/CVSlider0to10.svg
new file mode 100644
index 0000000..78564ee
--- /dev/null
+++ b/res/CVSlider0to10.svg
@@ -0,0 +1,4891 @@
+
+
+
+
diff --git a/src/AudioInterface16.cpp b/src/AudioInterface16.cpp
new file mode 100644
index 0000000..7255b4d
--- /dev/null
+++ b/src/AudioInterface16.cpp
@@ -0,0 +1,314 @@
+#include
+#include
+#include
+#include
+#include
+#include
+#include "GVerbWidget.hpp"
+#include "audio.hpp"
+#include "dsp/samplerate.hpp"
+#include "dsp/ringbuffer.hpp"
+
+
+#define AUDIO_OUTPUTS 16
+#define AUDIO_INPUTS 16
+
+
+using namespace rack;
+
+// Sound by Yaroslav Samoylov from the Noun Project
+
+struct AudioInterfaceIO16 : AudioIO {
+ std::mutex engineMutex;
+ std::condition_variable engineCv;
+ std::mutex audioMutex;
+ std::condition_variable audioCv;
+ // Audio thread produces, engine thread consumes
+ DoubleRingBuffer, (1<<15)> inputBuffer;
+ // Audio thread consumes, engine thread produces
+ DoubleRingBuffer, (1<<15)> outputBuffer;
+ bool active = false;
+
+ AudioInterfaceIO16() {
+ maxChannels = 16;
+ }
+
+ ~AudioInterfaceIO16() {
+ // Close stream here before destructing AudioInterfaceIO16, so the mutexes are still valid when waiting to close.
+ setDevice(-1, 0);
+ }
+
+ void processStream(const float *input, float *output, int frames) override {
+ // Reactivate idle stream
+ if (!active) {
+ active = true;
+ inputBuffer.clear();
+ outputBuffer.clear();
+ }
+
+ if (numInputs > 0) {
+ // TODO Do we need to wait on the input to be consumed here? Experimentally, it works fine if we don't.
+ for (int i = 0; i < frames; i++) {
+ if (inputBuffer.full())
+ break;
+ Frame inputFrame;
+ memset(&inputFrame, 0, sizeof(inputFrame));
+ memcpy(&inputFrame, &input[numInputs * i], numInputs * sizeof(float));
+ inputBuffer.push(inputFrame);
+ }
+ }
+
+ if (numOutputs > 0) {
+ std::unique_lock lock(audioMutex);
+ auto cond = [&] {
+ return (outputBuffer.size() >= (size_t) frames);
+ };
+ auto timeout = std::chrono::milliseconds(100);
+ if (audioCv.wait_for(lock, timeout, cond)) {
+ // Consume audio block
+ for (int i = 0; i < frames; i++) {
+ Frame f = outputBuffer.shift();
+ for (int j = 0; j < numOutputs; j++) {
+ output[numOutputs*i + j] = clamp(f.samples[j], -1.f, 1.f);
+ }
+ }
+ }
+ else {
+ // Timed out, fill output with zeros
+ memset(output, 0, frames * numOutputs * sizeof(float));
+ debug("Audio Interface IO underflow");
+ }
+ }
+
+ // Notify engine when finished processing
+ engineCv.notify_one();
+ }
+
+ void onCloseStream() override {
+ inputBuffer.clear();
+ outputBuffer.clear();
+ }
+
+ void onChannelsChange() override {
+ }
+};
+
+
+struct AudioInterface16 : Module {
+ enum ParamIds {
+ NUM_PARAMS
+ };
+ enum InputIds {
+ ENUMS(AUDIO_INPUT, AUDIO_INPUTS),
+ NUM_INPUTS
+ };
+ enum OutputIds {
+ ENUMS(AUDIO_OUTPUT, AUDIO_OUTPUTS),
+ NUM_OUTPUTS
+ };
+ enum LightIds {
+ ENUMS(INPUT_LIGHT, AUDIO_INPUTS / 2),
+ ENUMS(OUTPUT_LIGHT, AUDIO_OUTPUTS / 2),
+ NUM_LIGHTS
+ };
+
+ AudioInterfaceIO16 audioIO;
+ int lastSampleRate = 0;
+ int lastNumOutputs = -1;
+ int lastNumInputs = -1;
+
+ SampleRateConverter inputSrc;
+ SampleRateConverter outputSrc;
+
+ // in rack's sample rate
+ DoubleRingBuffer, 16> inputBuffer;
+ DoubleRingBuffer, 16> outputBuffer;
+
+ AudioInterface16() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {
+ onSampleRateChange();
+ }
+
+ void step() override;
+
+ json_t *toJson() override {
+ json_t *rootJ = json_object();
+ json_object_set_new(rootJ, "audio", audioIO.toJson());
+ return rootJ;
+ }
+
+ void fromJson(json_t *rootJ) override {
+ json_t *audioJ = json_object_get(rootJ, "audio");
+ audioIO.fromJson(audioJ);
+ }
+
+ void onReset() override {
+ audioIO.setDevice(-1, 0);
+ }
+};
+
+
+void AudioInterface16::step() {
+ // Update SRC states
+ int sampleRate = (int) engineGetSampleRate();
+ inputSrc.setRates(audioIO.sampleRate, sampleRate);
+ outputSrc.setRates(sampleRate, audioIO.sampleRate);
+
+ inputSrc.setChannels(audioIO.numInputs);
+ outputSrc.setChannels(audioIO.numOutputs);
+
+ // Inputs: audio engine -> rack engine
+ if (audioIO.active && audioIO.numInputs > 0) {
+ // Wait until inputs are present
+ // Give up after a timeout in case the audio device is being unresponsive.
+ std::unique_lock lock(audioIO.engineMutex);
+ auto cond = [&] {
+ return (!audioIO.inputBuffer.empty());
+ };
+ auto timeout = std::chrono::milliseconds(200);
+ if (audioIO.engineCv.wait_for(lock, timeout, cond)) {
+ // Convert inputs
+ int inLen = audioIO.inputBuffer.size();
+ int outLen = inputBuffer.capacity();
+ inputSrc.process(audioIO.inputBuffer.startData(), &inLen, inputBuffer.endData(), &outLen);
+ audioIO.inputBuffer.startIncr(inLen);
+ inputBuffer.endIncr(outLen);
+ }
+ else {
+ // Give up on pulling input
+ audioIO.active = false;
+ debug("Audio Interface underflow");
+ }
+ }
+
+ // Take input from buffer
+ Frame inputFrame;
+ if (!inputBuffer.empty()) {
+ inputFrame = inputBuffer.shift();
+ }
+ else {
+ memset(&inputFrame, 0, sizeof(inputFrame));
+ }
+ for (int i = 0; i < audioIO.numInputs; i++) {
+ outputs[AUDIO_OUTPUT + i].value = 10.f * inputFrame.samples[i];
+ }
+ for (int i = audioIO.numInputs; i < AUDIO_INPUTS; i++) {
+ outputs[AUDIO_OUTPUT + i].value = 0.f;
+ }
+
+ // Outputs: rack engine -> audio engine
+ if (audioIO.active && audioIO.numOutputs > 0) {
+ // Get and push output SRC frame
+ if (!outputBuffer.full()) {
+ Frame outputFrame;
+ for (int i = 0; i < AUDIO_OUTPUTS; i++) {
+ outputFrame.samples[i] = inputs[AUDIO_INPUT + i].value / 10.f;
+ }
+ outputBuffer.push(outputFrame);
+ }
+
+ if (outputBuffer.full()) {
+ // Wait until enough outputs are consumed
+ // Give up after a timeout in case the audio device is being unresponsive.
+ std::unique_lock lock(audioIO.engineMutex);
+ auto cond = [&] {
+ return (audioIO.outputBuffer.size() < (size_t) audioIO.blockSize);
+ };
+ auto timeout = std::chrono::milliseconds(200);
+ if (audioIO.engineCv.wait_for(lock, timeout, cond)) {
+ // Push converted output
+ int inLen = outputBuffer.size();
+ int outLen = audioIO.outputBuffer.capacity();
+ outputSrc.process(outputBuffer.startData(), &inLen, audioIO.outputBuffer.endData(), &outLen);
+ outputBuffer.startIncr(inLen);
+ audioIO.outputBuffer.endIncr(outLen);
+ }
+ else {
+ // Give up on pushing output
+ audioIO.active = false;
+ outputBuffer.clear();
+ debug("Audio Interface underflow");
+ }
+ }
+
+ // Notify audio thread that an output is potentially ready
+ audioIO.audioCv.notify_one();
+ }
+
+ // Turn on light if at least one port is enabled in the nearby pair
+ for (int i = 0; i < AUDIO_INPUTS / 2; i++)
+ lights[INPUT_LIGHT + i].value = (audioIO.active && audioIO.numOutputs >= 2*i+1);
+ for (int i = 0; i < AUDIO_OUTPUTS / 2; i++)
+ lights[OUTPUT_LIGHT + i].value = (audioIO.active && audioIO.numInputs >= 2*i+1);
+}
+
+
+struct AudioInterfaceWidget16 : ModuleWidget {
+ AudioInterfaceWidget16(AudioInterface16 *module) : ModuleWidget(module) {
+ setPanel(SVG::load(assetPlugin(plugin, "res/AudioInterface16.svg")));
+
+ // addChild(Widget::create(Vec(RACK_GRID_WIDTH, 0)));
+ // addChild(Widget::create(Vec(box.size.x - 2 * RACK_GRID_WIDTH, 0)));
+ // addChild(Widget::create(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
+ // addChild(Widget::create(Vec(box.size.x - 2 * RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
+
+ addInput(Port::create(mm2px(Vec(3.7069211, 55.530807)), Port::INPUT, module, AudioInterface16::AUDIO_INPUT + 0));
+ addInput(Port::create(mm2px(Vec(15.307249, 55.530807)), Port::INPUT, module, AudioInterface16::AUDIO_INPUT + 1));
+ addInput(Port::create(mm2px(Vec(26.906193, 55.530807)), Port::INPUT, module, AudioInterface16::AUDIO_INPUT + 2));
+ addInput(Port::create(mm2px(Vec(38.506519, 55.530807)), Port::INPUT, module, AudioInterface16::AUDIO_INPUT + 3));
+ addInput(Port::create(mm2px(Vec(50.106845, 55.530807)), Port::INPUT, module, AudioInterface16::AUDIO_INPUT + 4));
+ addInput(Port::create(mm2px(Vec(61.707171, 55.530807)), Port::INPUT, module, AudioInterface16::AUDIO_INPUT + 5));
+ addInput(Port::create(mm2px(Vec(73.307497, 55.530807)), Port::INPUT, module, AudioInterface16::AUDIO_INPUT + 6));
+ addInput(Port::create(mm2px(Vec(84.907823, 55.530807)), Port::INPUT, module, AudioInterface16::AUDIO_INPUT + 7));
+ addInput(Port::create(mm2px(Vec(3.7069211, 70.144905)), Port::INPUT, module, AudioInterface16::AUDIO_INPUT + 8));
+ addInput(Port::create(mm2px(Vec(15.307249, 70.144905)), Port::INPUT, module, AudioInterface16::AUDIO_INPUT + 9));
+ addInput(Port::create(mm2px(Vec(26.906193, 70.144905)), Port::INPUT, module, AudioInterface16::AUDIO_INPUT + 10));
+ addInput(Port::create(mm2px(Vec(38.506519, 70.144905)), Port::INPUT, module, AudioInterface16::AUDIO_INPUT + 11));
+ addInput(Port::create(mm2px(Vec(50.106845, 70.144905)), Port::INPUT, module, AudioInterface16::AUDIO_INPUT + 12));
+ addInput(Port::create(mm2px(Vec(61.707171, 70.144905)), Port::INPUT, module, AudioInterface16::AUDIO_INPUT + 13));
+ addInput(Port::create(mm2px(Vec(73.307497, 70.144905)), Port::INPUT, module, AudioInterface16::AUDIO_INPUT + 14));
+ addInput(Port::create(mm2px(Vec(84.907823, 70.144905)), Port::INPUT, module, AudioInterface16::AUDIO_INPUT + 15));
+
+ addOutput(Port::create(mm2px(Vec(3.7069209, 92.143906)), Port::OUTPUT, module, AudioInterface16::AUDIO_OUTPUT + 0));
+ addOutput(Port::create(mm2px(Vec(15.307249, 92.143906)), Port::OUTPUT, module, AudioInterface16::AUDIO_OUTPUT + 1));
+ addOutput(Port::create(mm2px(Vec(26.906193, 92.143906)), Port::OUTPUT, module, AudioInterface16::AUDIO_OUTPUT + 2));
+ addOutput(Port::create(mm2px(Vec(38.506519, 92.143906)), Port::OUTPUT, module, AudioInterface16::AUDIO_OUTPUT + 3));
+ addOutput(Port::create(mm2px(Vec(50.106845, 92.143906)), Port::OUTPUT, module, AudioInterface16::AUDIO_OUTPUT + 4));
+ addOutput(Port::create(mm2px(Vec(61.707171, 92.143906)), Port::OUTPUT, module, AudioInterface16::AUDIO_OUTPUT + 5));
+ addOutput(Port::create(mm2px(Vec(73.307497, 92.143906)), Port::OUTPUT, module, AudioInterface16::AUDIO_OUTPUT + 6));
+ addOutput(Port::create(mm2px(Vec(84.907823, 92.143906)), Port::OUTPUT, module, AudioInterface16::AUDIO_OUTPUT + 7));
+ addOutput(Port::create(mm2px(Vec(3.7069209, 108.1443)), Port::OUTPUT, module, AudioInterface16::AUDIO_OUTPUT + 8));
+ addOutput(Port::create(mm2px(Vec(15.307249, 108.1443)), Port::OUTPUT, module, AudioInterface16::AUDIO_OUTPUT + 9));
+ addOutput(Port::create(mm2px(Vec(26.906193, 108.1443)), Port::OUTPUT, module, AudioInterface16::AUDIO_OUTPUT + 10));
+ addOutput(Port::create(mm2px(Vec(38.506519, 108.1443)), Port::OUTPUT, module, AudioInterface16::AUDIO_OUTPUT + 11));
+ addOutput(Port::create(mm2px(Vec(50.106845, 108.1443)), Port::OUTPUT, module, AudioInterface16::AUDIO_OUTPUT + 12));
+ addOutput(Port::create(mm2px(Vec(61.707171, 108.1443)), Port::OUTPUT, module, AudioInterface16::AUDIO_OUTPUT + 13));
+ addOutput(Port::create(mm2px(Vec(73.307497, 108.1443)), Port::OUTPUT, module, AudioInterface16::AUDIO_OUTPUT + 14));
+ addOutput(Port::create(mm2px(Vec(84.907823, 108.1443)), Port::OUTPUT, module, AudioInterface16::AUDIO_OUTPUT + 15));
+
+ addChild(ModuleLightWidget::create>(mm2px(Vec(12.524985, 54.577202)), module, AudioInterface16::INPUT_LIGHT + 0));
+ addChild(ModuleLightWidget::create>(mm2px(Vec(35.725647, 54.577202)), module, AudioInterface16::INPUT_LIGHT + 1));
+ addChild(ModuleLightWidget::create>(mm2px(Vec(58.926309, 54.577202)), module, AudioInterface16::INPUT_LIGHT + 2));
+ addChild(ModuleLightWidget::create>(mm2px(Vec(82.126971, 54.577202)), module, AudioInterface16::INPUT_LIGHT + 3));
+ addChild(ModuleLightWidget::create>(mm2px(Vec(12.524985, 69.158226)), module, AudioInterface16::INPUT_LIGHT + 4));
+ addChild(ModuleLightWidget::create>(mm2px(Vec(35.725647, 69.158226)), module, AudioInterface16::INPUT_LIGHT + 5));
+ addChild(ModuleLightWidget::create>(mm2px(Vec(58.926309, 69.158226)), module, AudioInterface16::INPUT_LIGHT + 6));
+ addChild(ModuleLightWidget::create>(mm2px(Vec(82.126971, 69.158226)), module, AudioInterface16::INPUT_LIGHT + 7));
+
+ addChild(ModuleLightWidget::create>(mm2px(Vec(12.524985, 91.147583)), module, AudioInterface16::OUTPUT_LIGHT + 0));
+ addChild(ModuleLightWidget::create>(mm2px(Vec(35.725647, 91.147583)), module, AudioInterface16::OUTPUT_LIGHT + 1));
+ addChild(ModuleLightWidget::create>(mm2px(Vec(58.926309, 91.147583)), module, AudioInterface16::OUTPUT_LIGHT + 2));
+ addChild(ModuleLightWidget::create>(mm2px(Vec(82.126971, 91.147583)), module, AudioInterface16::OUTPUT_LIGHT + 3));
+ addChild(ModuleLightWidget::create>(mm2px(Vec(12.524985, 107.17003)), module, AudioInterface16::OUTPUT_LIGHT + 4));
+ addChild(ModuleLightWidget::create>(mm2px(Vec(35.725647, 107.17003)), module, AudioInterface16::OUTPUT_LIGHT + 5));
+ addChild(ModuleLightWidget::create>(mm2px(Vec(58.926309, 107.17003)), module, AudioInterface16::OUTPUT_LIGHT + 6));
+ addChild(ModuleLightWidget::create>(mm2px(Vec(82.126971, 107.17003)), module, AudioInterface16::OUTPUT_LIGHT + 7));
+
+ AudioWidget *audioWidget = Widget::create(mm2px(Vec(3.2122073, 10.837339)));
+ audioWidget->box.size = mm2px(Vec(90.5, 28));
+ audioWidget->audioIO = &module->audioIO;
+ addChild(audioWidget);
+ }
+};
+
+
+Model *modelAudioInterface16 = Model::create("rcm", "AudioInterface16", "Audio 16", EXTERNAL_TAG);
\ No newline at end of file
diff --git a/src/GVerbModule.cpp b/src/GVerbModule.cpp
index 66d7e99..73394f3 100644
--- a/src/GVerbModule.cpp
+++ b/src/GVerbModule.cpp
@@ -200,20 +200,20 @@ void GVerbModule::step() {
auto R_L = 0.f, R_R = 0.f;
if (gverbL != NULL) {
- gverb_do(gverbL, inputs[LEFT_AUDIO].value, &L_L, &L_R);
+ gverb_do(gverbL, inputs[LEFT_AUDIO].value / 10.f, &L_L, &L_R);
- L_L = isfinite(L_L) ? L_L : 0.f;
- L_R = isfinite(L_R) ? L_R : 0.f;
+ L_L = isfinite(L_L) ? L_L * 10.f : 0.f;
+ L_R = isfinite(L_R) ? L_R * 10.f : 0.f;
}
auto L_L_S = (L_L + ((1-spread) * L_R)) / (2-spread);
auto L_R_S = (L_R + ((1-spread) * L_L)) / (2-spread);
if (gverbR != NULL) {
- gverb_do(gverbR, inputs[RIGHT_AUDIO].value, &R_L, &R_R);
+ gverb_do(gverbR, inputs[RIGHT_AUDIO].value / 10.f, &R_L, &R_R);
- R_L = isfinite(R_L) ? R_L : 0.f;
- R_R = isfinite(R_R) ? R_R : 0.f;
+ R_L = isfinite(R_L) ? R_L * 10.f : 0.f;
+ R_R = isfinite(R_R) ? R_R * 10.f : 0.f;
}
auto R_L_S = (R_L + ((1-spread) * R_R)) / (2-spread);
diff --git a/src/GVerbWidget.cpp b/src/GVerbWidget.cpp
index 5043031..bd7d3ed 100644
--- a/src/GVerbWidget.cpp
+++ b/src/GVerbWidget.cpp
@@ -1,8 +1,18 @@
#include "GVerbWidget.hpp"
+#include
-Plugin *plugin;
+#if ARCH_WIN
+ #include
+ #include
+ #define mkdir(_dir, _perms) _mkdir(_dir)
+#else
+ #include
+#endif
+
+using namespace std;
+Plugin *plugin;
void init(Plugin *p) {
plugin = p;
@@ -11,7 +21,8 @@ void init(Plugin *p) {
// Add all Models defined throughout the plugin
p->addModel(modelGVerbModule);
- p->addModel(modelDuckModule);
+ p->addModel(modelLoadCounterModule);
+ p->addModel(modelAudioInterface16);
p->addModel(modelCV0to10Module);
p->addModel(modelCVS0to10Module);
p->addModel(modelCV5to5Module);
diff --git a/src/GVerbWidget.hpp b/src/GVerbWidget.hpp
index e770b59..874d2c9 100644
--- a/src/GVerbWidget.hpp
+++ b/src/GVerbWidget.hpp
@@ -14,3 +14,4 @@ extern Model *modelCVS0to10Module;
extern Model *modelCV5to5Module;
extern Model *modelCVMmtModule;
extern Model *modelCVTglModule;
+extern Model *modelAudioInterface16;
diff --git a/src/LoadCounter.cpp b/src/LoadCounter.cpp
new file mode 100644
index 0000000..88433bb
--- /dev/null
+++ b/src/LoadCounter.cpp
@@ -0,0 +1,66 @@
+#include "GVerbWidget.hpp"
+#include
+
+struct LoadCounterModule : Module {
+ enum ParamIds {
+ NUM_PARAMS
+ };
+ enum InputIds {
+ NUM_INPUTS
+ };
+ enum OutputIds {
+ NUM_OUTPUTS
+ };
+ enum LightIds {
+ NUM_LIGHTS
+ };
+
+ LoadCounterModule() : Module(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS) {
+ }
+ void step() override;
+
+ int counter = 0;
+
+ // For more advanced Module features, read Rack's engine.hpp header file
+ // - toJson, fromJson: serialization of internal data
+ // - onSampleRateChange: event triggered by a change of sample rate
+ // - onReset, onRandomize, onCreate, onDelete: implements special behavior when user clicks these from the context menu
+};
+
+void LoadCounterModule::step() {
+ int n = 8;
+ for (int i = 1; i <= n; ++i)
+ {
+ std::vector x;
+ x.resize(50);
+ int m = 500;
+ for (auto &v : x)
+ {
+ v = 500 - m++; //rand();
+ }
+
+ std::sort(x.begin(), x.end());
+ }
+}
+
+struct CKSSWhite : SVGSwitch, ToggleSwitch {
+ CKSSWhite() {
+ addFrame(SVG::load(assetPlugin(plugin, "res/CKSS_0_White.svg")));
+ addFrame(SVG::load(assetPlugin(plugin, "res/CKSS_1_White.svg")));
+ }
+};
+
+struct LoadCounterModuleWidget : ModuleWidget {
+ TextField *textField;
+
+ LoadCounterModuleWidget(LoadCounterModule *module) : ModuleWidget(module) {
+ setPanel(SVG::load(assetPlugin(plugin, "res/CVTgl.svg")));
+ }
+};
+
+
+// Specify the Module and ModuleWidget subclass, human-readable
+// author name for categorization per plugin, module slug (should never
+// change), human-readable module name, and any number of tags
+// (found in `include/tags.hpp`) separated by commas.
+Model *modelLoadCounterModule = Model::create("rcm", "rcm-counter", "Load Counter", ENVELOPE_FOLLOWER_TAG);