diff --git a/.github/workflows/build-plugin.yml b/.github/workflows/build-plugin.yml
deleted file mode 100644
index ec63601..0000000
--- a/.github/workflows/build-plugin.yml
+++ /dev/null
@@ -1,84 +0,0 @@
-name: Build VCV Rack Plugin
-on: [push, pull_request]
-
-env:
- rack-sdk-version: 2.4.1
- rack-plugin-toolchain-dir: /home/build/rack-plugin-toolchain
-
-defaults:
- run:
- shell: bash
-
-jobs:
- build:
- name: ${{ matrix.platform }}
- runs-on: ubuntu-latest
- container:
- image: ghcr.io/qno/rack-plugin-toolchain-win-linux
- options: --user root
- strategy:
- fail-fast: false
- matrix:
- platform: [win-x64, lin-x64]
- steps:
- - uses: actions/checkout@v3
- with:
- submodules: recursive
- - name: Build plugin
- run: |
- export PLUGIN_DIR=$GITHUB_WORKSPACE
- pushd ${{ env.rack-plugin-toolchain-dir }}
- make plugin-build-${{ matrix.platform }}
- - name: Upload artifact
- uses: actions/upload-artifact@v3
- with:
- path: ${{ env.rack-plugin-toolchain-dir }}/plugin-build
- name: ${{ matrix.platform }}
-
- build-mac:
- name: mac
- runs-on: macos-12
- strategy:
- fail-fast: false
- matrix:
- platform: [x64, arm64]
- steps:
- - uses: actions/checkout@v3
- with:
- submodules: recursive
- - name: Get Rack-SDK
- run: |
- pushd $HOME
- curl -o Rack-SDK.zip https://vcvrack.com/downloads/Rack-SDK-${{ env.rack-sdk-version }}-mac-${{ matrix.platform }}.zip
- unzip Rack-SDK.zip
- - name: Build plugin
- run: |
- CROSS_COMPILE_TARGET_x64=x86_64-apple-darwin
- CROSS_COMPILE_TARGET_arm64=arm64-apple-darwin
- export RACK_DIR=$HOME/Rack-SDK
- export CROSS_COMPILE=$CROSS_COMPILE_TARGET_${{ matrix.platform }}
- make dep
- make dist
- echo "Plugin architecture '$(lipo -archs plugin.dylib)'"
- - name: Upload artifact
- uses: actions/upload-artifact@v3
- with:
- path: dist/*.vcvplugin
- name: mac-${{ matrix.platform }}
-
- publish:
- name: Publish plugin
- runs-on: ubuntu-latest
- needs: [build, build-mac]
- steps:
- - uses: actions/download-artifact@v3
- with:
- path: _artifacts
- - uses: "marvinpinto/action-automatic-releases@latest"
- with:
- repo_token: "${{ secrets.GITHUB_TOKEN }}"
- automatic_release_tag: "latest"
- prerelease: true
- title: "Development Build"
- files: |
- _artifacts/**/*.vcvplugin
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3d9c489..0142fca 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,11 +1,11 @@
# Change Log
-## v2.7.0 (in progress)
+## v2.7.0
* Midi Thing 2
* Initial release
- * PonyVCF
- * Initial release
+ * Octaves
+ * Better default oversampling setting (x4)
## v2.6.0
diff --git a/plugin.json b/plugin.json
index f5fbe02..8bc5d32 100644
--- a/plugin.json
+++ b/plugin.json
@@ -343,18 +343,6 @@
"Oscillator",
"Polyphonic"
]
- },
- {
- "slug": "PonyVCF",
- "name": "PonyVCF",
- "description": "Space-conscious lowpass filter and volume processor.",
- "manualUrl": "https://www.befaco.org/pony-vcf/",
- "modularGridUrl": "https://www.modulargrid.net/e/befaco-pony-vcf-",
- "tags": [
- "Hardware clone",
- "Mixer",
- "Filter"
- ]
}
]
}
diff --git a/res/panels/PonyVCF.svg b/res/panels/PonyVCF.svg
deleted file mode 100644
index 00edd01..0000000
--- a/res/panels/PonyVCF.svg
+++ /dev/null
@@ -1,1147 +0,0 @@
-
-
-
-
diff --git a/src/PonyVCF.cpp b/src/PonyVCF.cpp
deleted file mode 100644
index 1ed763a..0000000
--- a/src/PonyVCF.cpp
+++ /dev/null
@@ -1,224 +0,0 @@
-#include "plugin.hpp"
-
-using simd::float_4;
-
-// filter engine is just Fundemental VCF from https://github.com/VCVRack/Fundamental/blob/v2/src/VCF.cpp for now
-// GPL-v3
-
-
-template
-static T clip(T x) {
- // return std::tanh(x);
- // Pade approximant of tanh
- x = simd::clamp(x, -3.f, 3.f);
- return x * (27 + x * x) / (27 + 9 * x * x);
-}
-
-
-template
-struct LadderFilter {
- T omega0;
- T resonance = 1;
- T state[4];
- T input;
-
- LadderFilter() {
- reset();
- setCutoff(0);
- }
-
- void reset() {
- for (int i = 0; i < 4; i++) {
- state[i] = 0;
- }
- }
-
- void setCutoff(T cutoff) {
- omega0 = 2 * T(M_PI) * cutoff;
- }
-
- void process(T input, T dt) {
- dsp::stepRK4(T(0), dt, state, 4, [&](T t, const T x[], T dxdt[]) {
- T inputt = crossfade(this->input, input, t / dt);
- T inputc = clip(inputt - resonance * x[3]);
- T yc0 = clip(x[0]);
- T yc1 = clip(x[1]);
- T yc2 = clip(x[2]);
- T yc3 = clip(x[3]);
-
- dxdt[0] = omega0 * (inputc - yc0);
- dxdt[1] = omega0 * (yc0 - yc1);
- dxdt[2] = omega0 * (yc1 - yc2);
- dxdt[3] = omega0 * (yc2 - yc3);
- });
-
- this->input = input;
- }
-
- T lowpass() {
- return state[3];
- }
- T highpass() {
- return clip((input - resonance * state[3]) - 4 * state[0] + 6 * state[1] - 4 * state[2] + state[3]);
- }
-};
-
-
-struct PonyVCF : Module {
- enum ParamId {
- CV1_PARAM,
- RES_PARAM,
- FREQ_PARAM,
- GAIN1_PARAM,
- GAIN2_PARAM,
- GAIN3_PARAM,
- ROUTING_PARAM,
- PARAMS_LEN
- };
- enum InputId {
- IN1_INPUT,
- RES_INPUT,
- VCA_INPUT,
- IN2_INPUT,
- CV1_INPUT,
- IN3_INPUT,
- CV2_INPUT,
- INPUTS_LEN
- };
- enum OutputId {
- OUTPUT,
- OUTPUTS_LEN
- };
- enum LightId {
- IN2_LIGHT,
- IN1_LIGHT,
- LIGHTS_LEN
- };
-
- LadderFilter filters[4];
-
- PonyVCF() {
- config(PARAMS_LEN, INPUTS_LEN, OUTPUTS_LEN, LIGHTS_LEN);
- configParam(CV1_PARAM, 0.f, 1.f, 0.f, "CV1 Attenuator");
- configParam(RES_PARAM, 0.f, 1.f, 0.f, "Resonance");
- configParam(FREQ_PARAM, 0.f, 1.f, 0.f, "Frequency");
- configParam(GAIN1_PARAM, 0.f, 1.2f, 1.f, "Gain Channel 1");
- configParam(GAIN2_PARAM, 0.f, 1.2f, 1.f, "Gain Channel 2");
- configParam(GAIN3_PARAM, 0.f, 1.2f, 1.f, "Gain Channel 3");
- configParam(ROUTING_PARAM, 0.f, 1.f, 0.f, "VCA routing");
-
- configInput(IN1_INPUT, "Channel 1");
- configInput(RES_INPUT, "Resonance CV");
- configInput(VCA_INPUT, "VCA");
- configInput(IN2_INPUT, "Channel 2");
- configInput(CV1_INPUT, "Frequency (CV1)");
- configInput(IN3_INPUT, "Channel 3");
- configInput(CV2_INPUT, "Frequency (CV2)");
-
- configOutput(OUTPUT, "Main");
-
- onReset();
- }
-
-
- void onReset() override {
- for (int i = 0; i < 4; i++)
- filters[i].reset();
- }
-
- float_4 prevOut[4] = {};
-
- void process(const ProcessArgs& args) override {
- if (!outputs[OUTPUT].isConnected()) {
- return;
- }
-
- float resParam = params[RES_PARAM].getValue();
- float freqParam = params[FREQ_PARAM].getValue();
- float freqCvParam = params[CV1_PARAM].getValue();
-
-
- int channels = std::max({1, inputs[IN1_INPUT].getChannels(), inputs[IN2_INPUT].getChannels(), inputs[IN3_INPUT].getChannels()});
-
- for (int c = 0; c < channels; c += 4) {
- auto& filter = filters[c / 4];
-
- float_4 input = inputs[IN1_INPUT].getVoltageSimd(c) * params[GAIN1_PARAM].getValue();
- input += inputs[IN2_INPUT].getVoltageSimd(c) * params[GAIN2_PARAM].getValue();
- input += inputs[IN3_INPUT].getNormalVoltageSimd(prevOut[c / 4], c) * params[GAIN3_PARAM].getValue();
-
-
- // input = Saturator::process(input / 5.0f) * 1.1f;
- input = clip(input / 5.0f) * 1.1f;
-
- // Add -120dB noise to bootstrap self-oscillation
- input += 1e-6f * (2.f * random::uniform() - 1.f);
-
- // Set resonance
- float_4 resonance = resParam + inputs[RES_INPUT].getPolyVoltageSimd(c) / 10.f;
- resonance = clamp(resonance, 0.f, 1.f);
- filter.resonance = simd::pow(resonance, 2) * 10.f;
-
- // Get pitch
- float_4 pitch = 5 * freqParam + inputs[CV1_INPUT].getPolyVoltageSimd(c) * freqCvParam + inputs[CV2_INPUT].getPolyVoltageSimd(c);
- // Set cutoff
- float_4 cutoff = dsp::FREQ_C4 * dsp::exp2_taylor5(pitch);
- // Without oversampling, we must limit to 8000 Hz or so @ 44100 Hz
- cutoff = clamp(cutoff, 1.f, args.sampleRate / 2.f);
-
- // Without oversampling, we must limit to 8000 Hz or so @ 44100 Hz
- cutoff = clamp(cutoff, 1.f, args.sampleRate * 0.18f);
- filter.setCutoff(cutoff);
-
- // Set outputs
- filter.process(input, args.sampleTime);
- if (outputs[OUTPUT].isConnected()) {
- float_4 resGain = 1.0f / (0.05 + 0.9 * dsp::exp2_taylor5(-8.f * simd::pow(resonance, 2.0)));
- // float_4 resGain = (1.0f + 8.f * resonance); // 1st order empirical fit
- float_4 out = 5.f * filter.lowpass() * resGain;
- outputs[OUTPUT].setVoltageSimd(out, c);
-
- prevOut[c / 4] = out;
- }
-
- // DEBUG("channel %d %g", channels, input[0]);
- }
-
- outputs[OUTPUT].setChannels(channels);
- }
-};
-
-
-struct PonyVCFWidget : ModuleWidget {
- PonyVCFWidget(PonyVCF* module) {
- setModule(module);
- setPanel(createPanel(asset::plugin(pluginInstance, "res/panels/PonyVCF.svg")));
-
- addChild(createWidget(Vec(RACK_GRID_WIDTH, 0)));
- addChild(createWidget(Vec(RACK_GRID_WIDTH, RACK_GRID_HEIGHT - RACK_GRID_WIDTH)));
-
- addParam(createParamCentered(mm2px(Vec(7.62, 14.5)), module, PonyVCF::CV1_PARAM));
- addParam(createParamCentered(mm2px(Vec(22.38, 14.5)), module, PonyVCF::RES_PARAM));
- addParam(createParamCentered(mm2px(Vec(15.0, 35.001)), module, PonyVCF::FREQ_PARAM));
- addParam(createParam(mm2px(Vec(3.217, 48.584)), module, PonyVCF::GAIN1_PARAM));
- addParam(createParam(mm2px(Vec(13.271, 48.584)), module, PonyVCF::GAIN2_PARAM));
- addParam(createParam(mm2px(Vec(23.316, 48.584)), module, PonyVCF::GAIN3_PARAM));
- addParam(createParam(mm2px(Vec(23.498, 96.784)), module, PonyVCF::ROUTING_PARAM));
-
- addInput(createInputCentered(mm2px(Vec(5.0, 86.5)), module, PonyVCF::IN1_INPUT));
- addInput(createInputCentered(mm2px(Vec(15.0, 86.5)), module, PonyVCF::RES_INPUT));
- addInput(createInputCentered(mm2px(Vec(25.0, 86.5)), module, PonyVCF::VCA_INPUT));
- addInput(createInputCentered(mm2px(Vec(5.0, 100.0)), module, PonyVCF::IN2_INPUT));
- addInput(createInputCentered(mm2px(Vec(15.0, 100.0)), module, PonyVCF::CV1_INPUT));
- addInput(createInputCentered(mm2px(Vec(5.0, 113.5)), module, PonyVCF::IN3_INPUT));
- addInput(createInputCentered(mm2px(Vec(15.0, 113.5)), module, PonyVCF::CV2_INPUT));
-
- addOutput(createOutputCentered(mm2px(Vec(25.0, 113.5)), module, PonyVCF::OUTPUT));
-
- addChild(createLightCentered>(mm2px(Vec(2.578, 23.492)), module, PonyVCF::IN2_LIGHT));
- addChild(createLightCentered>(mm2px(Vec(2.578, 27.159)), module, PonyVCF::IN1_LIGHT));
- }
-};
-
-
-Model* modelPonyVCF = createModel("PonyVCF");
\ No newline at end of file
diff --git a/src/plugin.cpp b/src/plugin.cpp
index fa8f4bc..3a9f56d 100644
--- a/src/plugin.cpp
+++ b/src/plugin.cpp
@@ -32,5 +32,4 @@ void init(rack::Plugin *p) {
p->addModel(modelMidiThing);
p->addModel(modelVoltio);
p->addModel(modelOctaves);
- p->addModel(modelPonyVCF);
}