Cardinal/lv2export/includes/rack.hpp
falkTX 70d73741ee
Add valleyaudio-plateau lv2 export, WIP
Signed-off-by: falkTX <falktx@falktx.com>
2022-05-23 22:01:43 +01:00

1226 lines
35 KiB
C++

/*
* DISTRHO Cardinal Plugin
* Copyright (C) 2021-2022 Filipe Coelho <falktx@falktx.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 3 of
* the License, or any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* For a full copy of the GNU General Public License see the LICENSE file.
*/
/**
* This file contains a substantial amount of code from VCVRack, adjusted for inline use
* Copyright (C) 2016-2021 VCV.
*
* This program is free software: you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 3 of
* the License, or (at your option) any later version.
*/
#pragma once
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <list>
#include <memory>
#include <string>
#include <vector>
enum NVGalign {};
struct NVGcolor { float a; };
struct NVGpaint {};
inline NVGcolor nvgRGB(int r, int g, int b) { return {}; }
inline NVGcolor nvgRGBA(int r, int g, int b, int a) { return {}; }
inline NVGcolor nvgRGBf(float r, float g, float b) { return {}; }
inline NVGcolor nvgRGBAf(float r, float g, float b, float a) { return {}; }
inline void nvgBeginPath(void* vg) {}
inline void nvgFillColor(void* vg, NVGcolor) {}
inline void nvgFillPaint(void* vg, NVGpaint) {}
inline void nvgFill(void* vg) {}
inline void nvgStrokeColor(void* vg, NVGcolor) {}
inline void nvgStrokeWidth(void* vg, float) {}
inline void nvgStroke(void* vg) {}
inline void nvgRect(void* vg, float a, float b, float c, float d) {}
inline void nvgImageSize(void*, int, void*, void*) {}
inline NVGpaint nvgImagePattern(void*, float, float, float, float, float, int handle, float) { return {}; }
struct json_t {};
json_t* json_boolean(bool) { return NULL; }
json_t* json_integer(int) { return NULL; }
json_t* json_object() { return NULL; }
json_t* json_object_get(json_t*, const char*) { return NULL; }
bool json_boolean_value(json_t*) { return false; }
int json_integer_value(json_t*) { return 0; }
void json_object_set_new(json_t*, const char*, json_t*) {}
namespace rack {
struct Quantity {
virtual ~Quantity() {}
virtual void setValue(float value) {}
virtual float getValue() { return 0.f; }
virtual float getMinValue() { return 0.f; }
virtual float getMaxValue() { return 1.f; }
virtual float getDefaultValue() { return 0.f; }
// virtual float getDisplayValue();
// virtual void setDisplayValue(float displayValue);
// virtual int getDisplayPrecision();
// virtual std::string getDisplayValueString();
// virtual void setDisplayValueString(std::string s);
virtual std::string getLabel() { return ""; }
virtual std::string getUnit() { return ""; }
// virtual std::string getString();
// virtual void reset();
// virtual void randomize();
// bool isMin();
// bool isMax();
// void setMin();
// void setMax();
// void toggle();
// void moveValue(float deltaValue);
// float getRange();
// bool isBounded();
// float toScaled(float value);
// float fromScaled(float scaledValue);
// void setScaledValue(float scaledValue);
// float getScaledValue();
// void moveScaledValue(float deltaScaledValue);
};
namespace ui {
struct Menu;
}
namespace math {
inline int clamp(int x, int a, int b) {
return std::max(std::min(x, b), a);
}
inline float clamp(float x, float a = 0.f, float b = 1.f) {
return std::fmax(std::fmin(x, b), a);
}
inline float rescale(float x, float xMin, float xMax, float yMin, float yMax) {
return yMin + (x - xMin) / (xMax - xMin) * (yMax - yMin);
}
struct Vec {
float x = 0.f;
float y = 0.f;
Vec() {}
Vec(float xy) : x(xy), y(xy) {}
Vec(float x, float y) : x(x), y(y) {}
Vec neg() const { return Vec(-x, -y); }
Vec plus(Vec b) const { return Vec(x + b.x, y + b.y); }
Vec minus(Vec b) const { return Vec(x - b.x, y - b.y); }
Vec mult(float s) const { return Vec(x * s, y * s); }
Vec mult(Vec b) const { return Vec(x * b.x, y * b.y); }
};
struct Rect {
Vec pos;
Vec size;
};
} // namespace math
namespace engine {
static constexpr const int PORT_MAX_CHANNELS = 16;
struct Module;
struct Engine {
float getSampleRate() { return sampleRate; }
// custom
float sampleRate = 0.f;
};
struct Light {
float value = 0.f;
void setBrightness(float brightness) {
value = brightness;
}
float getBrightness() {
return value;
}
void setBrightnessSmooth(float brightness, float deltaTime, float lambda = 30.f) {
if (brightness < value) {
// Fade out light
value += (brightness - value) * lambda * deltaTime;
}
else {
// Immediately illuminate light
value = brightness;
}
}
void setSmoothBrightness(float brightness, float deltaTime) {
setBrightnessSmooth(brightness, deltaTime);
}
void setBrightnessSmooth(float brightness, int frames = 1) {
setBrightnessSmooth(brightness, frames / 44100.f);
}
};
struct Param {
float value = 0.f;
float getValue() { return value; }
void setValue(float value) { this->value = value; }
};
struct Port {
union {
float voltages[PORT_MAX_CHANNELS] = {};
float value;
};
union {
uint8_t channels = 0;
uint8_t active;
};
Light plugLights[3];
enum Type {
INPUT,
OUTPUT,
};
void setVoltage(float voltage, int channel = 0) { voltages[channel] = voltage; }
float getVoltage(int channel = 0) { return voltages[channel]; }
float getPolyVoltage(int channel) { return isMonophonic() ? getVoltage(0) : getVoltage(channel); }
float getNormalVoltage(float normalVoltage, int channel = 0) { return isConnected() ? getVoltage(channel) : normalVoltage; }
float getNormalPolyVoltage(float normalVoltage, int channel) { return isConnected() ? getPolyVoltage(channel) : normalVoltage; }
float* getVoltages(int firstChannel = 0) { return &voltages[firstChannel]; }
void readVoltages(float* v) {
for (int c = 0; c < channels; c++) {
v[c] = voltages[c];
}
}
void writeVoltages(const float* v) {
for (int c = 0; c < channels; c++) {
voltages[c] = v[c];
}
}
void clearVoltages() {
for (int c = 0; c < channels; c++) {
voltages[c] = 0.f;
}
}
float getVoltageSum() {
float sum = 0.f;
for (int c = 0; c < channels; c++) {
sum += voltages[c];
}
return sum;
}
float getVoltageRMS() {
if (channels == 0) {
return 0.f;
}
else if (channels == 1) {
return std::fabs(voltages[0]);
}
else {
float sum = 0.f;
for (int c = 0; c < channels; c++) {
sum += std::pow(voltages[c], 2);
}
return std::sqrt(sum);
}
}
// template <typename T>
// T getVoltageSimd(int firstChannel) {
// return T::load(&voltages[firstChannel]);
// }
//
// template <typename T>
// T getPolyVoltageSimd(int firstChannel) {
// return isMonophonic() ? getVoltage(0) : getVoltageSimd<T>(firstChannel);
// }
//
// template <typename T>
// T getNormalVoltageSimd(T normalVoltage, int firstChannel) {
// return isConnected() ? getVoltageSimd<T>(firstChannel) : normalVoltage;
// }
//
// template <typename T>
// T getNormalPolyVoltageSimd(T normalVoltage, int firstChannel) {
// return isConnected() ? getPolyVoltageSimd<T>(firstChannel) : normalVoltage;
// }
//
// template <typename T>
// void setVoltageSimd(T voltage, int firstChannel) {
// voltage.store(&voltages[firstChannel]);
// }
void setChannels(int channels) {
if (this->channels == 0) {
return;
}
for (int c = channels; c < this->channels; c++) {
voltages[c] = 0.f;
}
if (channels == 0) {
channels = 1;
}
this->channels = channels;
}
int getChannels() { return channels; }
bool isConnected() { return channels > 0; }
bool isMonophonic() { return channels == 1; }
bool isPolyphonic() { return channels > 1; }
float normalize(float normalVoltage) { return getNormalVoltage(normalVoltage); }
};
struct Output : Port {};
struct Input : Port {};
struct PortInfo {
Module* module = NULL;
Port::Type type = Port::INPUT;
int portId = -1;
std::string name;
std::string description;
virtual ~PortInfo() {}
virtual std::string getName() {
if (name == "")
return std::string("#") + std::to_string(portId + 1);
return name;
}
std::string getFullName() {
std::string name = getName();
name += " ";
name += (type == Port::INPUT) ? "input" : "output";
return name;
}
virtual std::string getDescription() { return description; }
};
struct ParamQuantity : Quantity {
Module* module = NULL;
int paramId = -1;
float minValue = 0.f;
float maxValue = 1.f;
float defaultValue = 0.f;
std::string name;
std::string unit;
float displayBase = 0.f;
float displayMultiplier = 1.f;
float displayOffset = 0.f;
int displayPrecision = 5;
std::string description;
bool resetEnabled = true;
bool randomizeEnabled = true;
bool smoothEnabled = false;
bool snapEnabled = false;
// Param* getParam();
// /** If smoothEnabled is true, requests to the engine to smoothly move to a target value each sample. */
// void setSmoothValue(float value);
// float getSmoothValue();
// void setValue(float value) override;
// float getValue() override;
float getMinValue() override { return minValue; }
float getMaxValue() override { return maxValue; }
float getDefaultValue() override { return defaultValue; }
// float getDisplayValue() override;
// void setDisplayValue(float displayValue) override;
// std::string getDisplayValueString() override;
// void setDisplayValueString(std::string s) override;
// int getDisplayPrecision() override;
// std::string getLabel() override;
// std::string getUnit() override;
// void reset() override;
// void randomize() override;
virtual std::string getDescription() { return description; }
// virtual json_t* toJson();
// virtual void fromJson(json_t* rootJ);
};
struct SwitchQuantity : ParamQuantity {
// std::vector<std::string> labels;
// std::string getDisplayValueString() override;
// void setDisplayValueString(std::string s) override;
};
struct Module {
std::vector<Param> params;
std::vector<Input> inputs;
std::vector<Output> outputs;
std::vector<Light> lights;
std::vector<ParamQuantity*> paramQuantities;
std::vector<PortInfo*> inputInfos;
std::vector<PortInfo*> outputInfos;
// std::vector<LightInfo*> lightInfos;
virtual ~Module() {
for (ParamQuantity* paramQuantity : paramQuantities) {
if (paramQuantity)
delete paramQuantity;
}
for (PortInfo* inputInfo : inputInfos) {
if (inputInfo)
delete inputInfo;
}
for (PortInfo* outputInfo : outputInfos) {
if (outputInfo)
delete outputInfo;
}
// for (LightInfo* lightInfo : lightInfos) {
// if (lightInfo)
// delete lightInfo;
// }
}
void config(int numParams, int numInputs, int numOutputs, int numLights = 0) {
// // This method should only be called once.
// assert(params.empty() && inputs.empty() && outputs.empty() && lights.empty() && paramQuantities.empty());
params.resize(numParams);
inputs.resize(numInputs);
outputs.resize(numOutputs);
lights.resize(numLights);
paramQuantities.resize(numParams);
for (int i = 0; i < numParams; i++) {
configParam(i, 0.f, 1.f, 0.f);
}
inputInfos.resize(numInputs);
for (int i = 0; i < numInputs; i++) {
configInput(i);
}
outputInfos.resize(numOutputs);
for (int i = 0; i < numOutputs; i++) {
configOutput(i);
}
// lightInfos.resize(numLights);
}
template <class TParamQuantity = ParamQuantity>
TParamQuantity* configParam(int paramId, float minValue, float maxValue, float defaultValue, std::string name = "", std::string unit = "", float displayBase = 0.f, float displayMultiplier = 1.f, float displayOffset = 0.f) {
// assert(paramId < (int) params.size() && paramId < (int) paramQuantities.size());
if (paramQuantities[paramId])
delete paramQuantities[paramId];
TParamQuantity* q = new TParamQuantity;
q->ParamQuantity::module = this;
q->ParamQuantity::paramId = paramId;
q->ParamQuantity::minValue = minValue;
q->ParamQuantity::maxValue = maxValue;
q->ParamQuantity::defaultValue = defaultValue;
q->ParamQuantity::name = name;
q->ParamQuantity::unit = unit;
q->ParamQuantity::displayBase = displayBase;
q->ParamQuantity::displayMultiplier = displayMultiplier;
q->ParamQuantity::displayOffset = displayOffset;
paramQuantities[paramId] = q;
Param* p = &params[paramId];
p->value = q->getDefaultValue();
return q;
}
template <class TSwitchQuantity = SwitchQuantity>
TSwitchQuantity* configSwitch(int paramId, float minValue, float maxValue, float defaultValue, std::string name = "", std::vector<std::string> labels = {}) {
TSwitchQuantity* sq = configParam<TSwitchQuantity>(paramId, minValue, maxValue, defaultValue, name);
sq->labels = labels;
return sq;
}
template <class TSwitchQuantity = SwitchQuantity>
TSwitchQuantity* configButton(int paramId, std::string name = "") {
TSwitchQuantity* sq = configParam<TSwitchQuantity>(paramId, 0.f, 1.f, 0.f, name);
sq->randomizeEnabled = false;
return sq;
}
template <class TPortInfo = PortInfo>
TPortInfo* configInput(int portId, std::string name = "") {
// assert(portId < (int) inputs.size() && portId < (int) inputInfos.size());
if (inputInfos[portId])
delete inputInfos[portId];
TPortInfo* info = new TPortInfo;
info->PortInfo::module = this;
info->PortInfo::type = Port::INPUT;
info->PortInfo::portId = portId;
info->PortInfo::name = name;
inputInfos[portId] = info;
return info;
}
template <class TPortInfo = PortInfo>
TPortInfo* configOutput(int portId, std::string name = "") {
// assert(portId < (int) outputs.size() && portId < (int) outputInfos.size());
if (outputInfos[portId])
delete outputInfos[portId];
TPortInfo* info = new TPortInfo;
info->PortInfo::module = this;
info->PortInfo::type = Port::OUTPUT;
info->PortInfo::portId = portId;
info->PortInfo::name = name;
outputInfos[portId] = info;
return info;
}
// template <class TLightInfo = LightInfo>
// TLightInfo* configLight(int lightId, std::string name = "") {
// assert(lightId < (int) lights.size() && lightId < (int) lightInfos.size());
// if (lightInfos[lightId])
// delete lightInfos[lightId];
//
// TLightInfo* info = new TLightInfo;
// info->LightInfo::module = this;
// info->LightInfo::lightId = lightId;
// info->LightInfo::name = name;
// lightInfos[lightId] = info;
// return info;
// }
void configBypass(int inputId, int outputId) {
// assert(inputId < (int) inputs.size());
// assert(outputId < (int) outputs.size());
// // Check that output is not yet routed
// for (BypassRoute& br : bypassRoutes) {
// assert(br.outputId != outputId);
// }
//
// BypassRoute br;
// br.inputId = inputId;
// br.outputId = outputId;
// bypassRoutes.push_back(br);
}
int getNumParams() { return params.size(); }
Param& getParam(int index) { return params[index]; }
int getNumInputs() { return inputs.size(); }
Input& getInput(int index) { return inputs[index]; }
int getNumOutputs() { return outputs.size(); }
Output& getOutput(int index) { return outputs[index]; }
int getNumLights() { return lights.size(); }
Light& getLight(int index) { return lights[index]; }
ParamQuantity* getParamQuantity(int index) { return paramQuantities[index]; }
PortInfo* getInputInfo(int index) { return inputInfos[index]; }
PortInfo* getOutputInfo(int index) { return outputInfos[index]; }
// LightInfo* getLightInfo(int index) { return lightInfos[index]; }
struct ProcessArgs {
float sampleRate;
float sampleTime;
int64_t frame;
};
virtual void process(const ProcessArgs& args) {
step();
}
virtual void step() {}
// virtual void processBypass(const ProcessArgs& args);
// virtual json_t* toJson();
// virtual void fromJson(json_t* rootJ);
/** Serializes the "params" object. */
// virtual json_t* paramsToJson();
// virtual void paramsFromJson(json_t* rootJ);
virtual json_t* dataToJson() { return NULL; }
virtual void dataFromJson(json_t* rootJ) {}
struct SampleRateChangeEvent {
float sampleRate;
float sampleTime;
};
virtual void onSampleRateChange(const SampleRateChangeEvent&) {
onSampleRateChange();
}
struct ResetEvent {};
virtual void onReset(const ResetEvent&) {} // TODO
virtual void onAdd() {}
virtual void onRemove() {}
virtual void onReset() {}
virtual void onRandomize() {}
virtual void onSampleRateChange() {}
// private
void doProcess(const ProcessArgs& args) {
// if (!internal->bypassed)
process(args);
// else
// processBypass(args);
// if (args.frame % PORT_DIVIDER == 0) {
// float portTime = args.sampleTime * PORT_DIVIDER;
// for (Input& input : inputs) {
// Port_step(&input, portTime);
// }
// for (Output& output : outputs) {
// Port_step(&output, portTime);
// }
// }
}
};
} // namespace engine
namespace widget {
struct BaseEvent {
};
struct Widget {
math::Rect box;
Widget* parent = NULL;
std::list<Widget*> children;
bool visible = true;
bool requestedDelete = false;
using BaseEvent = widget::BaseEvent;
struct PositionBaseEvent {
math::Vec pos;
};
struct HoverEvent : BaseEvent, PositionBaseEvent {
math::Vec mouseDelta;
};
virtual void onHover(const HoverEvent&) {
}
struct ButtonEvent : BaseEvent, PositionBaseEvent {
int button;
int action;
int mods;
};
virtual void onButton(const ButtonEvent&) {
}
struct DoubleClickEvent : BaseEvent {};
virtual void onDoubleClick(const DoubleClickEvent&) {}
struct KeyBaseEvent {
int key;
int scancode;
std::string keyName;
int action;
int mods;
};
struct HoverKeyEvent : BaseEvent, PositionBaseEvent, KeyBaseEvent {};
virtual void onHoverKey(const HoverKeyEvent&) {
}
struct TextBaseEvent {
int codepoint;
};
struct HoverTextEvent : BaseEvent, PositionBaseEvent, TextBaseEvent {};
virtual void onHoverText(const HoverTextEvent&) {
}
struct HoverScrollEvent : BaseEvent, PositionBaseEvent {
math::Vec scrollDelta;
};
virtual void onHoverScroll(const HoverScrollEvent&) {
}
struct EnterEvent : BaseEvent {};
virtual void onEnter(const EnterEvent&) {}
struct LeaveEvent : BaseEvent {};
virtual void onLeave(const LeaveEvent&) {}
struct SelectEvent : BaseEvent {};
virtual void onSelect(const SelectEvent&) {}
struct DeselectEvent : BaseEvent {};
virtual void onDeselect(const DeselectEvent&) {}
struct SelectKeyEvent : BaseEvent, KeyBaseEvent {};
virtual void onSelectKey(const SelectKeyEvent&) {}
struct SelectTextEvent : BaseEvent, TextBaseEvent {};
virtual void onSelectText(const SelectTextEvent&) {}
struct DragBaseEvent : BaseEvent {
int button;
};
struct DragStartEvent : DragBaseEvent {};
virtual void onDragStart(const DragStartEvent&) {}
struct DragEndEvent : DragBaseEvent {};
virtual void onDragEnd(const DragEndEvent&) {}
struct DragMoveEvent : DragBaseEvent {
math::Vec mouseDelta;
};
virtual void onDragMove(const DragMoveEvent&) {}
struct DragHoverEvent : DragBaseEvent, PositionBaseEvent {
Widget* origin = NULL;
math::Vec mouseDelta;
};
virtual void onDragHover(const DragHoverEvent&) {
}
struct DragEnterEvent : DragBaseEvent {
Widget* origin = NULL;
};
virtual void onDragEnter(const DragEnterEvent&) {}
struct DragLeaveEvent : DragBaseEvent {
Widget* origin = NULL;
};
virtual void onDragLeave(const DragLeaveEvent&) {}
struct DragDropEvent : DragBaseEvent {
Widget* origin = NULL;
};
virtual void onDragDrop(const DragDropEvent&) {}
struct PathDropEvent : BaseEvent, PositionBaseEvent {
PathDropEvent(const std::vector<std::string>& paths) : paths(paths) {}
const std::vector<std::string>& paths;
};
virtual void onPathDrop(const PathDropEvent&) {
}
struct ActionEvent : BaseEvent {};
virtual void onAction(const ActionEvent&) {}
struct ChangeEvent : BaseEvent {};
virtual void onChange(const ChangeEvent&) {}
bool hasChild(Widget* child) { return false; }
void addChild(Widget* child) {}
void addChildBottom(Widget* child) {}
void addChildBelow(Widget* child, Widget* sibling) {}
void addChildAbove(Widget* child, Widget* sibling) {}
void removeChild(Widget* child) {}
void clearChildren() {}
virtual void step() {}
struct DrawArgs {
void* vg = NULL;
math::Rect clipBox;
void* fb = NULL;
};
virtual void draw(const DrawArgs& args);
};
struct OpaqueWidget : Widget {
};
struct SvgWidget : Widget {
void wrap() {}
void setSvg(void* svg) {}
};
struct TransparentWidget : Widget {
};
} // namespace widget
namespace app {
static constexpr const float RACK_GRID_WIDTH = 15;
static constexpr const float RACK_GRID_HEIGHT = 380;
// static constexpr const math::Vec RACK_GRID_SIZE = math::Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT);
// static constexpr const math::Vec RACK_OFFSET = RACK_GRID_SIZE.mult(math::Vec(2000, 100));
struct CircularShadow : widget::TransparentWidget {
float blurRadius;
float opacity;
};
struct LightWidget : widget::TransparentWidget {
NVGcolor bgColor, color, borderColor;
};
struct ModuleWidget : widget::OpaqueWidget {
// plugin::Model* model = NULL;
engine::Module* module = NULL;
void setModel(void*) {}
void setModule(void*) {}
void setPanel(void*) {}
void addParam(void*) {}
void addInput(void*) {}
void addOutput(void*) {}
virtual void appendContextMenu(ui::Menu* menu) {}
};
struct MultiLightWidget : LightWidget {
// std::vector<NVGcolor> baseColors;
// int getNumColors();
void addBaseColor(NVGcolor baseColor) {}
// void setBrightnesses(const std::vector<float>& brightnesses);
};
struct ModuleLightWidget : MultiLightWidget {
// engine::Module* module = NULL;
// int firstLightId = -1;
// ModuleLightWidget();
// ~ModuleLightWidget();
// engine::Light* getLight(int colorId);
// engine::LightInfo* getLightInfo();
// void createTooltip();
// void destroyTooltip();
};
struct ParamWidget : widget::OpaqueWidget {
engine::Module* module = NULL;
int paramId = -1;
virtual void initParamQuantity() {}
engine::ParamQuantity* getParamQuantity() { return module ? module->paramQuantities[paramId] : NULL; }
void createTooltip() {}
void destroyTooltip() {}
void createContextMenu();
virtual void appendContextMenu(void* menu) {}
void resetAction();
};
struct PortWidget : widget::OpaqueWidget {
};
struct Knob : ParamWidget {
bool horizontal = false;
bool smooth = true;
bool snap = false;
float speed = 1.f;
bool forceLinear = false;
float minAngle = -M_PI;
float maxAngle = M_PI;
};
struct SliderKnob : Knob {
};
struct Switch : ParamWidget {
bool momentary = false;
};
struct SvgKnob : Knob {
CircularShadow* shadow;
void setSvg(void* svg) {}
};
struct SvgPanel : widget::Widget {
// widget::FramebufferWidget* fb;
// widget::SvgWidget* sw;
// PanelBorder* panelBorder;
void setBackground(void* svg) {}
};
struct SvgPort : PortWidget {
// widget::FramebufferWidget* fb;
CircularShadow* shadow;
// widget::SvgWidget* sw;
void setSvg(void* svg) {}
};
struct SvgScrew : widget::Widget {
// widget::FramebufferWidget* fb;
widget::SvgWidget* sw;
void setSvg(void* svg) {}
};
struct SvgSlider : app::SliderKnob {
// widget::FramebufferWidget* fb;
widget::SvgWidget* background;
// widget::SvgWidget* handle;
math::Vec minHandlePos, maxHandlePos;
void setBackgroundSvg(void* svg) {}
void setHandleSvg(void* svg) {}
void setHandlePos(math::Vec minHandlePos, math::Vec maxHandlePos) {}
void setHandlePosCentered(math::Vec minHandlePosCentered, math::Vec maxHandlePosCentered) {}
};
struct SvgSwitch : Switch {
// widget::FramebufferWidget* fb;
// CircularShadow* shadow;
// widget::SvgWidget* sw;
// std::vector<std::shared_ptr<window::Svg>> frames;
bool latch = false;
void addFrame(void* svg) {}
};
} // namespace app
namespace asset {
const char* plugin(void* instance, const char* path) {
return NULL;
}
} // namespace asset
namespace componentlibrary {
static constexpr const NVGcolor SCHEME_LIGHT_GRAY = {};
template <typename TBase = app::ModuleLightWidget>
struct TSvgLight : TBase {
// widget::FramebufferWidget* fb;
// widget::SvgWidget* sw;
void setSvg(void* svg) {}
};
using SvgLight = TSvgLight<>;
template <typename TBase = app::ModuleLightWidget>
struct TGrayModuleLightWidget : TBase {
};
using GrayModuleLightWidget = TGrayModuleLightWidget<>;
template <typename TBase = GrayModuleLightWidget>
struct TWhiteLight : TBase {
};
using WhiteLight = TWhiteLight<>;
template <typename TBase = GrayModuleLightWidget>
struct TRedLight : TBase {
};
using RedLight = TRedLight<>;
template <typename TBase = GrayModuleLightWidget>
struct TGreenLight : TBase {
};
using GreenLight = TGreenLight<>;
template <typename TBase = GrayModuleLightWidget>
struct TBlueLight : TBase {
};
using BlueLight = TBlueLight<>;
template <typename TBase = GrayModuleLightWidget>
struct TYellowLight : TBase {
};
using YellowLight = TYellowLight<>;
template <typename TBase = GrayModuleLightWidget>
struct TGreenRedLight : TBase {
};
using GreenRedLight = TGreenRedLight<>;
template <typename TBase = GrayModuleLightWidget>
struct TRedGreenBlueLight : TBase {
};
using RedGreenBlueLight = TRedGreenBlueLight<>;
template <typename TBase>
struct LargeLight : TSvgLight<TBase> {
};
template <typename TBase>
struct MediumLight : TSvgLight<TBase> {
};
template <typename TBase>
struct SmallLight : TSvgLight<TBase> {
};
template <typename TBase>
struct TinyLight : TSvgLight<TBase> {
};
struct ScrewBlack : app::SvgScrew {
};
} // namespace componentlibrary
namespace dsp {
inline float sinc(float x) {
if (x == 0.f)
return 1.f;
x *= M_PI;
return std::sin(x) / x;
}
// template <typename T>
// T sinc(T x) {
// T zeromask = (x == 0.f);
// x *= M_PI;
// x = simd::sin(x) / x;
// return simd::ifelse(zeromask, 1.f, x);
// }
template <typename T>
inline T blackmanHarris(T p) {
return
+ T(0.35875)
- T(0.48829) * std::cos(2 * T(M_PI) * p)
+ T(0.14128) * std::cos(4 * T(M_PI) * p)
- T(0.01168) * std::cos(6 * T(M_PI) * p);
}
inline void blackmanHarrisWindow(float* x, int len) {
for (int i = 0; i < len; i++) {
x[i] *= blackmanHarris(float(i) / (len - 1));
}
}
inline void boxcarLowpassIR(float* out, int len, float cutoff = 0.5f) {
for (int i = 0; i < len; i++) {
float t = i - (len - 1) / 2.f;
out[i] = 2 * cutoff * sinc(2 * cutoff * t);
}
}
template <int OVERSAMPLE, int QUALITY, typename T = float>
struct Decimator {
T inBuffer[OVERSAMPLE * QUALITY];
float kernel[OVERSAMPLE * QUALITY];
int inIndex;
Decimator(float cutoff = 0.9f) {
boxcarLowpassIR(kernel, OVERSAMPLE * QUALITY, cutoff * 0.5f / OVERSAMPLE);
blackmanHarrisWindow(kernel, OVERSAMPLE * QUALITY);
reset();
}
void reset() {
inIndex = 0;
std::memset(inBuffer, 0, sizeof(inBuffer));
}
T process(T* in) {
std::memcpy(&inBuffer[inIndex], in, OVERSAMPLE * sizeof(T));
inIndex += OVERSAMPLE;
inIndex %= OVERSAMPLE * QUALITY;
T out = 0.f;
for (int i = 0; i < OVERSAMPLE * QUALITY; i++) {
int index = inIndex - 1 - i;
index = (index + OVERSAMPLE * QUALITY) % (OVERSAMPLE * QUALITY);
out += kernel[i] * inBuffer[index];
}
return out;
}
};
struct PulseGenerator {
float remaining = 0.f;
void reset() { remaining = 0.f; }
bool process(float deltaTime) {
if (remaining > 0.f) {
remaining -= deltaTime;
return true;
}
return false;
}
void trigger(float duration = 1e-3f) {
if (duration > remaining) {
remaining = duration;
}
}
};
} // namespace dsp
namespace event {
using Base = widget::BaseEvent;
using PositionBase = widget::Widget::PositionBaseEvent;
using KeyBase = widget::Widget::KeyBaseEvent;
using TextBase = widget::Widget::TextBaseEvent;
using Hover = widget::Widget::HoverEvent;
using Button = widget::Widget::ButtonEvent;
using DoubleClick = widget::Widget::DoubleClickEvent;
using HoverKey = widget::Widget::HoverKeyEvent;
using HoverText = widget::Widget::HoverTextEvent;
using HoverScroll = widget::Widget::HoverScrollEvent;
using Enter = widget::Widget::EnterEvent;
using Leave = widget::Widget::LeaveEvent;
using Select = widget::Widget::SelectEvent;
using Deselect = widget::Widget::DeselectEvent;
using SelectKey = widget::Widget::SelectKeyEvent;
using SelectText = widget::Widget::SelectTextEvent;
using DragBase = widget::Widget::DragBaseEvent;
using DragStart = widget::Widget::DragStartEvent;
using DragEnd = widget::Widget::DragEndEvent;
using DragMove = widget::Widget::DragMoveEvent;
using DragHover = widget::Widget::DragHoverEvent;
using DragEnter = widget::Widget::DragEnterEvent;
using DragLeave = widget::Widget::DragLeaveEvent;
using DragDrop = widget::Widget::DragDropEvent;
using PathDrop = widget::Widget::PathDropEvent;
using Action = widget::Widget::ActionEvent;
using Change = widget::Widget::ChangeEvent;
// using Dirty = widget::Widget::DirtyEvent;
// using Reposition = widget::Widget::RepositionEvent;
// using Resize = widget::Widget::ResizeEvent;
// using Add = widget::Widget::AddEvent;
// using Remove = widget::Widget::RemoveEvent;
// using Show = widget::Widget::ShowEvent;
// using Hide = widget::Widget::HideEvent;
} // namespace event
namespace plugin {
struct Model {
virtual ~Model() {}
virtual engine::Module* createModule() = 0;
};
struct Plugin {
};
} // namespace plugin
namespace ui {
struct Button : widget::OpaqueWidget {
std::string text;
Quantity* quantity = NULL;
};
struct ChoiceButton : Button {
};
struct Menu : widget::OpaqueWidget {
// Menu* parentMenu = NULL;
// Menu* childMenu = NULL;
// MenuEntry* activeEntry = NULL;
// BNDcornerFlags cornerFlags = BND_CORNER_NONE;
// void setChildMenu(Menu* menu) {}
};
struct MenuEntry : widget::OpaqueWidget {
};
struct MenuItem : MenuEntry {
std::string text;
std::string rightText;
bool disabled = false;
};
struct MenuLabel : MenuEntry {
std::string text;
};
} // namespace ui
namespace window {
static constexpr const float SVG_DPI = 75.f;
static constexpr const float MM_PER_IN = 25.4f;
inline float in2px(float in) { return in * SVG_DPI; }
inline math::Vec in2px(math::Vec in) { return in.mult(SVG_DPI); }
inline float mm2px(float mm) { return mm * (SVG_DPI / MM_PER_IN); }
inline math::Vec mm2px(math::Vec mm) { return mm.mult(SVG_DPI / MM_PER_IN); }
struct Image {
int handle;
};
struct Window {
std::shared_ptr<Image> loadImage(const std::string&) { return {}; }
void* loadSvg(const void*) { return NULL; }
};
};
using namespace app;
using namespace componentlibrary;
using namespace engine;
using namespace math;
using namespace ui;
using namespace widget;
using namespace window;
using plugin::Plugin;
using plugin::Model;
template <class TModule, class TModuleWidget>
plugin::Model* createModel(std::string slug) {
struct TModel : plugin::Model {
engine::Module* createModule() override {
return new TModule;
}
};
return new TModel;
}
template <typename T>
T* construct() { return NULL; }
template <typename T, typename F, typename V, typename... Args>
T* construct(F f, V v, Args... args) { return NULL; }
template <class TWidget>
TWidget* createWidget(math::Vec pos) {
return NULL;
}
template <class TParamWidget>
TParamWidget* createParam(math::Vec pos, engine::Module* module, int paramId) {
return NULL;
}
template <class TParamWidget>
TParamWidget* createParamCentered(math::Vec pos, engine::Module* module, int paramId) {
return NULL;
}
template <class TPortWidget>
TPortWidget* createInput(math::Vec pos, engine::Module* module, int inputId) {
return NULL;
}
template <class TPortWidget>
TPortWidget* createInputCentered(math::Vec pos, engine::Module* module, int inputId) {
return NULL;
}
template <class TPortWidget>
TPortWidget* createOutput(math::Vec pos, engine::Module* module, int outputId) {
return NULL;
}
template <class TPortWidget>
TPortWidget* createOutputCentered(math::Vec pos, engine::Module* module, int outputId) {
return NULL;
}
template <class TModuleLightWidget>
TModuleLightWidget* createLight(math::Vec pos, engine::Module* module, int firstLightId) {
return NULL;
}
template <class TModuleLightWidget>
TModuleLightWidget* createLightCentered(math::Vec pos, engine::Module* module, int firstLightId) {
return NULL;
}
struct Context {
engine::Engine _engine;
window::Window _window;
engine::Engine* engine = &_engine;
window::Window* window = &_window;
};
Context* contextGet();
void contextSet(Context* context);
} // namespace rack
#define APP rack::contextGet()