Browse Source

Updating Sampling Modulator after having access to hardware

* sync just moves to next step, doesn't reset
* added (optional) DC removal
* implemented hold input

removed force_link_glibc_2.23.h (comes with sdk)
tags/v2.1.0
hemmer 3 years ago
parent
commit
696bbc2c6f
3 changed files with 59 additions and 3791 deletions
  1. +9
    -21
      .github/workflows/build-plugin.yml
  2. +50
    -43
      src/SamplingModulator.cpp
  3. +0
    -3727
      src/force_link_glibc_2.23.h

+ 9
- 21
.github/workflows/build-plugin.yml View File

@@ -43,10 +43,10 @@ jobs:
if: runner.os == 'Windows'
run: |
sed -i 's/zip -q -9 -r/7z a -tzip -mx=9/' $HOME/Rack-SDK/plugin.mk
- name: Patch Makefile to use old
- name: Patch Makefile to use old glibc versions
if: runner.os == 'Linux'
run: |
echo "FLAGS += -include src/force_link_glibc_2.23.h" >> Makefile
echo "FLAGS += -include force_link_glibc_2.23.h" >> Makefile
- name: Build plugin
run: |
${{ matrix.config.prepare-os }}
@@ -64,26 +64,14 @@ jobs:
runs-on: ubuntu-18.04
needs: build
steps:
- uses: actions/checkout@v2
- uses: FranzDiebold/github-env-vars-action@v1.2.1
- name: Create Release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: Release ${{ github.ref }}
body: |
${{ env.GITHUB_REPOSITORY_NAME }} VCV Rack Plugin ${{ env.GITHUB_REF_NAME }}
draft: false
prerelease: true
- uses: actions/download-artifact@v2
with:
path: _artifacts
- name: Upload release assets
uses: svenstaro/upload-release-action@v2
- uses: "marvinpinto/action-automatic-releases@latest"
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: _artifacts/**/*.zip
tag: ${{ github.ref }}
file_glob: true
repo_token: "${{ secrets.GITHUB_TOKEN }}"
automatic_release_tag: "latest"
prerelease: true
title: "Development Build"
files: |
_artifacts/**/*.zip

+ 50
- 43
src/SamplingModulator.cpp View File

@@ -73,18 +73,16 @@ struct SamplingModulator : Module {
}
};


int numEffectiveSteps = numSteps;
int currentStep = 0;
StepState stepStates[numSteps];
float triggerTime = 0;
bool triggerActive = false;

dsp::SchmittTrigger holdDetector;
dsp::SchmittTrigger clock;
dsp::MinBlepGenerator<16, 32> squareMinBlep;
dsp::MinBlepGenerator<16, 32> triggMinBlep;
dsp::MinBlepGenerator<16, 32> holdMinBlep;
bool applyMinBlep = true;
bool removeDC = true;

float stepPhase = 0.f;
float heldValue = 0.f;
@@ -104,25 +102,33 @@ struct SamplingModulator : Module {

void process(const ProcessArgs& args) override {
bool advanceStep = false;
holdDetector.process(rescale(inputs[HOLD_INPUT].getVoltage(), 0.1f, 2.f, 0.f, 1.f));

if (params[INT_EXT_PARAM].getValue() == CLOCK_EXTERNAL) {
// if external mode, the SYNC/EXT. CLOCK input acts as a clock
advanceStep = clock.process(rescale(inputs[SYNC_INPUT].getVoltage(), 0.1f, 2.f, 0.f, 1.f));
} else {
// if internal mode, the SYNC/EXT. CLOCK input acts as a sync
if (clock.process(rescale(inputs[SYNC_INPUT].getVoltage(), 0.1f, 2.f, 0.f, 1.f))) {
currentStep = 0;
}
else {
// if internal mode, the SYNC/EXT. CLOCK input acts as oscillator sync, resetting the phase
if (clock.process(rescale(inputs[SYNC_INPUT].getVoltage(), 0.1f, 2.f, 0.f, 1.f))) {
advanceStep = true;
stepPhase = 0.f;
halfPhase = false;
}
}
}

if (holdDetector.process(rescale(inputs[HOLD_INPUT].getVoltage(), 0.1f, 2.f, 0.f, 1.f))) {
float oldHeldValue = heldValue;
heldValue = inputs[IN_INPUT].getVoltage();
holdMinBlep.insertDiscontinuity(0, heldValue - oldHeldValue);
}

for (int i = 0; i < numSteps; i++) {
stepStates[i] = (StepState) params[STEP_PARAM + i].getValue();
}
int numActiveSteps = 0;
numEffectiveSteps = 8;
for (int i = 0; i < numSteps; i++) {
numActiveSteps += (stepStates[i] == STATE_ON);
if (stepStates[i] == STATE_RESET) {
numEffectiveSteps = i;
break;
@@ -130,7 +136,8 @@ struct SamplingModulator : Module {
}

const float pitch = 16.f * params[RATE_PARAM].getValue() + params[FINE_PARAM].getValue() + inputs[VOCT_INPUT].getVoltage();
const float frequency = 0.1 * simd::pow(2.f, pitch);
const float minDialFrequency = 1.0f;
const float frequency = minDialFrequency * simd::pow(2.f, pitch);

float oldPhase = stepPhase;
float deltaPhase = clamp(args.sampleTime * frequency, 1e-6f, 0.5f);
@@ -139,6 +146,10 @@ struct SamplingModulator : Module {
if (!halfPhase && stepPhase >= 0.5) {
float crossing = -(stepPhase - 0.5) / deltaPhase;
squareMinBlep.insertDiscontinuity(crossing, -2.f);
if (stepStates[currentStep] == STATE_ON) {
triggMinBlep.insertDiscontinuity(crossing, -2.f);
}

halfPhase = true;
}

@@ -154,44 +165,41 @@ struct SamplingModulator : Module {
}
}

if (triggerActive) {
triggerTime -= args.sampleTime;
if (triggerTime < 0) {
triggMinBlep.insertDiscontinuity(triggerTime, -2.f);
triggerTime = 0.;
triggerActive = false;
}
}

if (advanceStep) {
// TODO: what does reset on first step do?
currentStep = (currentStep + 1) % std::max(1, numEffectiveSteps);

if (stepStates[currentStep] == STATE_ON) {

float oldHeldValue = heldValue;
heldValue = inputs[IN_INPUT].getVoltage();;
triggerTime = 1e-3;
triggerActive = true;

float crossing = -(oldPhase + deltaPhase - 1.0) / deltaPhase;
// TODO: i guess should only be on if clock is internal?
const float crossing = -(oldPhase + deltaPhase - 1.0) / deltaPhase;
triggMinBlep.insertDiscontinuity(crossing, +2.f);
holdMinBlep.insertDiscontinuity(crossing, heldValue - oldHeldValue);

if (!holdDetector.isHigh()) {
float oldHeldValue = heldValue;
heldValue = inputs[IN_INPUT].getVoltage();
holdMinBlep.insertDiscontinuity(crossing, heldValue - oldHeldValue);
}
}
}

float output = heldValue + holdMinBlep.process() * applyMinBlep;
float output = heldValue + holdMinBlep.process();
outputs[OUT_OUTPUT].setVoltage(output);

// TODO: could calculate DC offset correction based on number of active bits
float triggerOut = triggerActive ? +1.f : -1.f;
triggerOut += triggMinBlep.process() * applyMinBlep;
outputs[TRIGG_OUTPUT].setVoltage(5.f * triggerOut);
float square = (stepPhase < 0.5) ? 2.f : 0.f;
square += squareMinBlep.process();


float trigger = (stepPhase < 0.5 && stepStates[currentStep] == STATE_ON) ? 2.f : 0.f;
trigger += triggMinBlep.process();

if (removeDC) {
trigger -= 1.0f;
square -= 1.0f;
if (numEffectiveSteps > 0) {
trigger += (float)(numEffectiveSteps - numActiveSteps) / (numEffectiveSteps);
}
}

float square = (stepPhase < 0.5) ? 1.f : -1.f;
square += squareMinBlep.process() * applyMinBlep;
outputs[CLOCK_OUTPUT].setVoltage(5.f * square);
outputs[TRIGG_OUTPUT].setVoltage(5.f * trigger);

for (int i = 0; i < numSteps; i++) {
lights[STEP_LIGHT + i].setBrightness(currentStep == i);
@@ -241,10 +249,10 @@ struct SamplingModulatorWidget : ModuleWidget {
addChild(createLightCentered<SmallLight<RedLight>>(mm2px(Vec(23.722, 94.617)), module, SamplingModulator::STEP_LIGHT + 7));
}

struct MinBLEPMenuItem : MenuItem {
struct DCMenuItem : MenuItem {
SamplingModulator* module;
void onAction(const event::Action& e) override {
module->applyMinBlep ^= true;
module->removeDC ^= true;
}
};

@@ -254,11 +262,10 @@ struct SamplingModulatorWidget : ModuleWidget {

menu->addChild(new MenuSeparator());

MinBLEPMenuItem* minBlepItem = createMenuItem<MinBLEPMenuItem>("Apply minBlep", CHECKMARK(module->applyMinBlep));
minBlepItem->module = module;
menu->addChild(minBlepItem);
DCMenuItem* dcItem = createMenuItem<DCMenuItem>("Remove DC Offset", CHECKMARK(module->removeDC));
dcItem->module = module;
menu->addChild(dcItem);
}

};



+ 0
- 3727
src/force_link_glibc_2.23.h
File diff suppressed because it is too large
View File


Loading…
Cancel
Save