Signed-off-by: hemmer <915048+hemmer@users.noreply.github.com>tags/v1.1.0^2
@@ -1,17 +1,7 @@ | |||||
#include "plugin.hpp" | #include "plugin.hpp" | ||||
#include "simd_mask.hpp" | |||||
#include "simd_input.hpp" | |||||
#define MAX(a,b) (a>b)?a:b | |||||
/* | |||||
static float clip(float x) { | |||||
// Pade approximant of x/(1 + x^12)^(1/12) | |||||
const float limit = 1.16691853009184; | |||||
x = clamp(x, -limit, limit); | |||||
return (x + 1.45833*std::pow(x, 13) + 0.559028*std::pow(x, 25) + 0.0427035*std::pow(x, 37)) | |||||
/ (1. + 1.54167*std::pow(x, 12) + 0.642361*std::pow(x, 24) + 0.0579909*std::pow(x, 36)); | |||||
} | |||||
*/ | |||||
static simd::float_4 clip4(simd::float_4 x) { | static simd::float_4 clip4(simd::float_4 x) { | ||||
// Pade approximant of x/(1 + x^12)^(1/12) | // Pade approximant of x/(1 + x^12)^(1/12) | ||||
@@ -67,8 +57,6 @@ struct ABC : Module { | |||||
NUM_LIGHTS | NUM_LIGHTS | ||||
}; | }; | ||||
ChannelMask channelMask; | |||||
ABC() { | ABC() { | ||||
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | ||||
@@ -79,24 +67,23 @@ struct ABC : Module { | |||||
} | } | ||||
void process(const ProcessArgs &args) override { | void process(const ProcessArgs &args) override { | ||||
simd::float_4 a1[4]; | |||||
simd::float_4 b1[4]; | |||||
simd::float_4 c1[4]; | |||||
simd::float_4 a1[4] = {}; | |||||
simd::float_4 b1[4] = {}; | |||||
simd::float_4 c1[4] = {}; | |||||
simd::float_4 out1[4]; | simd::float_4 out1[4]; | ||||
simd::float_4 a2[4]; | |||||
simd::float_4 b2[4]; | |||||
simd::float_4 c2[4]; | |||||
simd::float_4 a2[4] = {}; | |||||
simd::float_4 b2[4] = {}; | |||||
simd::float_4 c2[4] = {}; | |||||
simd::float_4 out2[4]; | simd::float_4 out2[4]; | ||||
int channels_1 = 1; | int channels_1 = 1; | ||||
int channels_2 = 1; | int channels_2 = 1; | ||||
memset(out1, 0, sizeof(out1)); | |||||
memset(out2, 0, sizeof(out2)); | |||||
// process upper section | // process upper section | ||||
@@ -106,15 +93,15 @@ struct ABC : Module { | |||||
int channels_B1 = inputs[B1_INPUT].getChannels(); | int channels_B1 = inputs[B1_INPUT].getChannels(); | ||||
int channels_C1 = inputs[C1_INPUT].getChannels(); | int channels_C1 = inputs[C1_INPUT].getChannels(); | ||||
channels_1 = MAX(channels_1, channels_A1); | |||||
channels_1 = MAX(channels_1, channels_B1); | |||||
channels_1 = MAX(channels_1, channels_C1); | |||||
channels_1 = std::max(channels_1, channels_A1); | |||||
channels_1 = std::max(channels_1, channels_B1); | |||||
channels_1 = std::max(channels_1, channels_C1); | |||||
float mult_B1 = (2.f/5.f)*exponentialBipolar80Pade_5_4(params[B1_LEVEL_PARAM].getValue()); | float mult_B1 = (2.f/5.f)*exponentialBipolar80Pade_5_4(params[B1_LEVEL_PARAM].getValue()); | ||||
float mult_C1 = exponentialBipolar80Pade_5_4(params[C1_LEVEL_PARAM].getValue()); | float mult_C1 = exponentialBipolar80Pade_5_4(params[C1_LEVEL_PARAM].getValue()); | ||||
load_input(inputs[A1_INPUT], a1, channels_A1); | |||||
channelMask.apply(a1, channels_1); | |||||
if(inputs[A1_INPUT].isConnected()) load_input(inputs[A1_INPUT], a1, channels_A1); | |||||
else memset(a1, 0, sizeof(a1)); | |||||
if(inputs[B1_INPUT].isConnected()) { | if(inputs[B1_INPUT].isConnected()) { | ||||
load_input(inputs[B1_INPUT], b1, channels_B1); | load_input(inputs[B1_INPUT], b1, channels_B1); | ||||
@@ -122,7 +109,6 @@ struct ABC : Module { | |||||
} else { | } else { | ||||
for(int c=0; c<channels_1; c+=4) b1[c/4] = simd::float_4(5.f*mult_B1); | for(int c=0; c<channels_1; c+=4) b1[c/4] = simd::float_4(5.f*mult_B1); | ||||
} | } | ||||
channelMask.apply(b1, channels_1); | |||||
if(inputs[C1_INPUT].isConnected()) { | if(inputs[C1_INPUT].isConnected()) { | ||||
load_input(inputs[C1_INPUT], c1, channels_C1); | load_input(inputs[C1_INPUT], c1, channels_C1); | ||||
@@ -130,7 +116,6 @@ struct ABC : Module { | |||||
} else { | } else { | ||||
for(int c=0; c<channels_1; c+=4) c1[c/4] = simd::float_4(10.f*mult_C1); | for(int c=0; c<channels_1; c+=4) c1[c/4] = simd::float_4(10.f*mult_C1); | ||||
} | } | ||||
channelMask.apply(c1, channels_1); | |||||
for(int c=0; c<channels_1; c+=4) out1[c/4] = clip4(a1[c/4] * b1[c/4] + c1[c/4]); | for(int c=0; c<channels_1; c+=4) out1[c/4] = clip4(a1[c/4] * b1[c/4] + c1[c/4]); | ||||
} | } | ||||
@@ -143,15 +128,15 @@ struct ABC : Module { | |||||
int channels_B2 = inputs[B2_INPUT].getChannels(); | int channels_B2 = inputs[B2_INPUT].getChannels(); | ||||
int channels_C2 = inputs[C2_INPUT].getChannels(); | int channels_C2 = inputs[C2_INPUT].getChannels(); | ||||
channels_2 = MAX(channels_2, channels_A2); | |||||
channels_2 = MAX(channels_2, channels_B2); | |||||
channels_2 = MAX(channels_2, channels_C2); | |||||
channels_2 = std::max(channels_2, channels_A2); | |||||
channels_2 = std::max(channels_2, channels_B2); | |||||
channels_2 = std::max(channels_2, channels_C2); | |||||
float mult_B2 = (2.f/5.f)*exponentialBipolar80Pade_5_4(params[B2_LEVEL_PARAM].getValue()); | float mult_B2 = (2.f/5.f)*exponentialBipolar80Pade_5_4(params[B2_LEVEL_PARAM].getValue()); | ||||
float mult_C2 = exponentialBipolar80Pade_5_4(params[C2_LEVEL_PARAM].getValue()); | float mult_C2 = exponentialBipolar80Pade_5_4(params[C2_LEVEL_PARAM].getValue()); | ||||
load_input(inputs[A2_INPUT], a2, channels_A2); | |||||
channelMask.apply(a2, channels_2); | |||||
if(inputs[A2_INPUT].isConnected()) load_input(inputs[A2_INPUT], a2, channels_A2); | |||||
else memset(a2, 0, sizeof(a2)); | |||||
if(inputs[B2_INPUT].isConnected()) { | if(inputs[B2_INPUT].isConnected()) { | ||||
load_input(inputs[B2_INPUT], b2, channels_B2); | load_input(inputs[B2_INPUT], b2, channels_B2); | ||||
@@ -159,7 +144,6 @@ struct ABC : Module { | |||||
} else { | } else { | ||||
for(int c=0; c<channels_2; c+=4) b2[c/4] = simd::float_4(5.f*mult_B2); | for(int c=0; c<channels_2; c+=4) b2[c/4] = simd::float_4(5.f*mult_B2); | ||||
} | } | ||||
channelMask.apply(b2, channels_2); | |||||
if(inputs[C2_INPUT].isConnected()) { | if(inputs[C2_INPUT].isConnected()) { | ||||
load_input(inputs[C2_INPUT], c2, channels_C2); | load_input(inputs[C2_INPUT], c2, channels_C2); | ||||
@@ -167,7 +151,6 @@ struct ABC : Module { | |||||
} else { | } else { | ||||
for(int c=0; c<channels_2; c+=4) c2[c/4] = simd::float_4(10.f*mult_C2); | for(int c=0; c<channels_2; c+=4) c2[c/4] = simd::float_4(10.f*mult_C2); | ||||
} | } | ||||
channelMask.apply(c2, channels_2); | |||||
for(int c=0; c<channels_2; c+=4) out2[c/4] = clip4(a2[c/4] * b2[c/4] + c2[c/4]); | for(int c=0; c<channels_2; c+=4) out2[c/4] = clip4(a2[c/4] * b2[c/4] + c2[c/4]); | ||||
}; | }; | ||||
@@ -180,7 +163,7 @@ struct ABC : Module { | |||||
} | } | ||||
else { | else { | ||||
for(int c=0; c<channels_1; c+=4) out2[c/4] += out1[c/4]; | for(int c=0; c<channels_1; c+=4) out2[c/4] += out1[c/4]; | ||||
channels_2 = MAX(channels_1, channels_2); | |||||
channels_2 = std::max(channels_1, channels_2); | |||||
} | } | ||||
if (outputs[OUT2_OUTPUT].isConnected()) { | if (outputs[OUT2_OUTPUT].isConnected()) { | ||||
@@ -1,5 +1,5 @@ | |||||
#include "plugin.hpp" | #include "plugin.hpp" | ||||
#include "simd_mask.hpp" | |||||
#include "simd_input.hpp" | |||||
struct DualAtenuverter : Module { | struct DualAtenuverter : Module { | ||||
@@ -1,7 +1,6 @@ | |||||
#include "plugin.hpp" | #include "plugin.hpp" | ||||
#include "simd_mask.hpp" | |||||
#include "simd_input.hpp" | |||||
#define MAX(a,b) (a>b)?a:b | |||||
struct EvenVCO : Module { | struct EvenVCO : Module { | ||||
enum ParamIds { | enum ParamIds { | ||||
@@ -45,8 +44,6 @@ struct EvenVCO : Module { | |||||
dsp::RCFilter triFilter; | dsp::RCFilter triFilter; | ||||
ChannelMask channelMask; | |||||
EvenVCO() { | EvenVCO() { | ||||
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS); | config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS); | ||||
configParam(OCTAVE_PARAM, -5.0, 4.0, 0.0, "Octave", "'", 0.5); | configParam(OCTAVE_PARAM, -5.0, 4.0, 0.0, "Octave", "'", 0.5); | ||||
@@ -78,9 +75,8 @@ struct EvenVCO : Module { | |||||
int channels_pwm = inputs[PWM_INPUT].getChannels(); | int channels_pwm = inputs[PWM_INPUT].getChannels(); | ||||
int channels = 1; | int channels = 1; | ||||
channels = MAX(channels, channels_pitch1); | |||||
channels = MAX(channels, channels_pitch2); | |||||
// channels = MAX(channels, channels_fm); | |||||
channels = std::max(channels, channels_pitch1); | |||||
channels = std::max(channels, channels_pitch2); | |||||
float pitch_0 = 1.f + std::round(params[OCTAVE_PARAM].getValue()) + params[TUNE_PARAM].getValue() / 12.f; | float pitch_0 = 1.f + std::round(params[OCTAVE_PARAM].getValue()) + params[TUNE_PARAM].getValue() / 12.f; | ||||
@@ -90,19 +86,16 @@ struct EvenVCO : Module { | |||||
if(inputs[PITCH1_INPUT].isConnected()) { | if(inputs[PITCH1_INPUT].isConnected()) { | ||||
load_input(inputs[PITCH1_INPUT], pitch_1, channels_pitch1); | load_input(inputs[PITCH1_INPUT], pitch_1, channels_pitch1); | ||||
channelMask.apply(pitch_1, channels_pitch1); | |||||
for(int c=0; c<channels_pitch1; c+=4) pitch[c/4] += pitch_1[c/4]; | for(int c=0; c<channels_pitch1; c+=4) pitch[c/4] += pitch_1[c/4]; | ||||
} | } | ||||
if(inputs[PITCH2_INPUT].isConnected()) { | if(inputs[PITCH2_INPUT].isConnected()) { | ||||
load_input(inputs[PITCH2_INPUT], pitch_2, channels_pitch2); | load_input(inputs[PITCH2_INPUT], pitch_2, channels_pitch2); | ||||
channelMask.apply(pitch_2, channels_pitch2); | |||||
for(int c=0; c<channels_pitch2; c+=4) pitch[c/4] += pitch_2[c/4]; | for(int c=0; c<channels_pitch2; c+=4) pitch[c/4] += pitch_2[c/4]; | ||||
} | } | ||||
if(inputs[FM_INPUT].isConnected()) { | if(inputs[FM_INPUT].isConnected()) { | ||||
load_input(inputs[FM_INPUT], pitch_fm, channels_fm); | load_input(inputs[FM_INPUT], pitch_fm, channels_fm); | ||||
channelMask.apply(pitch_fm, channels_fm); | |||||
for(int c=0; c<channels_fm; c+=4) pitch[c/4] += pitch_fm[c/4] / 4.f; | for(int c=0; c<channels_fm; c+=4) pitch[c/4] += pitch_fm[c/4] / 4.f; | ||||
} | } | ||||
@@ -120,7 +113,6 @@ struct EvenVCO : Module { | |||||
if(inputs[PWM_INPUT].isConnected()) { | if(inputs[PWM_INPUT].isConnected()) { | ||||
load_input(inputs[PWM_INPUT], pwm, channels_pwm); | load_input(inputs[PWM_INPUT], pwm, channels_pwm); | ||||
channelMask.apply(pwm, channels_pwm); | |||||
for(int c=0; c<channels_pwm; c+=4) pw[c/4] += pwm[c/4] / 5.f; | for(int c=0; c<channels_pwm; c+=4) pw[c/4] += pwm[c/4] / 5.f; | ||||
} | } | ||||
@@ -1,10 +1,7 @@ | |||||
#include "plugin.hpp" | #include "plugin.hpp" | ||||
#include "simd_mask.hpp" | |||||
#include "simd_input.hpp" | |||||
#define MAX(a,b) (a>b)?a:b | |||||
#define MIN(a,b) (a<b)?a:b | |||||
struct Mixer : Module { | struct Mixer : Module { | ||||
enum ParamIds { | enum ParamIds { | ||||
@@ -29,13 +26,12 @@ struct Mixer : Module { | |||||
enum LightIds { | enum LightIds { | ||||
OUT_POS_LIGHT, | OUT_POS_LIGHT, | ||||
OUT_NEG_LIGHT, | OUT_NEG_LIGHT, | ||||
OUT_BLUE_LIGHT, | |||||
NUM_LIGHTS | NUM_LIGHTS | ||||
}; | }; | ||||
simd::float_4 minus_one; | simd::float_4 minus_one; | ||||
ChannelMask channelMask; | |||||
Mixer() { | Mixer() { | ||||
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | ||||
configParam(CH1_PARAM, 0.0, 1.0, 0.0, "Ch 1 level", "%", 0, 100); | configParam(CH1_PARAM, 0.0, 1.0, 0.0, "Ch 1 level", "%", 0, 100); | ||||
@@ -44,71 +40,46 @@ struct Mixer : Module { | |||||
configParam(CH4_PARAM, 0.0, 1.0, 0.0, "Ch 4 level", "%", 0, 100); | configParam(CH4_PARAM, 0.0, 1.0, 0.0, "Ch 4 level", "%", 0, 100); | ||||
minus_one = simd::float_4(-1.0f); | minus_one = simd::float_4(-1.0f); | ||||
} | } | ||||
void process(const ProcessArgs &args) override { | void process(const ProcessArgs &args) override { | ||||
int i; | |||||
int channels1 = inputs[IN1_INPUT].getChannels(); | int channels1 = inputs[IN1_INPUT].getChannels(); | ||||
int channels2 = inputs[IN2_INPUT].getChannels(); | int channels2 = inputs[IN2_INPUT].getChannels(); | ||||
int channels3 = inputs[IN3_INPUT].getChannels(); | int channels3 = inputs[IN3_INPUT].getChannels(); | ||||
int channels4 = inputs[IN4_INPUT].getChannels(); | int channels4 = inputs[IN4_INPUT].getChannels(); | ||||
int out_channels = 1; | int out_channels = 1; | ||||
out_channels = MAX(out_channels, channels1); | |||||
out_channels = MAX(out_channels, channels2); | |||||
out_channels = MAX(out_channels, channels3); | |||||
out_channels = MAX(out_channels, channels4); | |||||
out_channels = std::max(out_channels, channels1); | |||||
out_channels = std::max(out_channels, channels2); | |||||
out_channels = std::max(out_channels, channels3); | |||||
out_channels = std::max(out_channels, channels4); | |||||
simd::float_4 mult1 = simd::float_4(params[CH1_PARAM].getValue()); | simd::float_4 mult1 = simd::float_4(params[CH1_PARAM].getValue()); | ||||
simd::float_4 mult2 = simd::float_4(params[CH2_PARAM].getValue()); | simd::float_4 mult2 = simd::float_4(params[CH2_PARAM].getValue()); | ||||
simd::float_4 mult3 = simd::float_4(params[CH3_PARAM].getValue()); | simd::float_4 mult3 = simd::float_4(params[CH3_PARAM].getValue()); | ||||
simd::float_4 mult4 = simd::float_4(params[CH4_PARAM].getValue()); | simd::float_4 mult4 = simd::float_4(params[CH4_PARAM].getValue()); | ||||
simd::float_4 in1[4]; | |||||
simd::float_4 in2[4]; | |||||
simd::float_4 in3[4]; | |||||
simd::float_4 in4[4]; | |||||
simd::float_4 out[4]; | simd::float_4 out[4]; | ||||
out[0] = simd::float_4(0.f); | |||||
out[1] = simd::float_4(0.f); | |||||
out[2] = simd::float_4(0.f); | |||||
out[3] = simd::float_4(0.f); | |||||
memset(out, 0, sizeof(out)); | |||||
if(inputs[IN1_INPUT].isConnected()) { | if(inputs[IN1_INPUT].isConnected()) { | ||||
// this also loads some spurious channels into in1[] | |||||
for(int c=0; c<channels1; c+=4) in1[c/4] = simd::float_4::load(inputs[IN1_INPUT].getVoltages(c)) * mult1; | |||||
for(i=0; i<channels1/4; i++) out[i] += in1[i]; // add only "real" channels. | |||||
out[i] += simd::float_4(_mm_and_ps(in1[i].v, channelMask[channels1-4*i].v)); // make sure we zero out spurious channels | |||||
for(int c=0; c<channels1; c+=4) out[c/4] += simd::float_4::load(inputs[IN1_INPUT].getVoltages(c)) * mult1; | |||||
} | } | ||||
if(inputs[IN2_INPUT].isConnected()) { | if(inputs[IN2_INPUT].isConnected()) { | ||||
for(int c=0; c<channels2; c+=4) in2[c/4] = simd::float_4::load(inputs[IN2_INPUT].getVoltages(c)) * mult2; | |||||
for(i=0; i<channels2/4; i++) out[i] += in2[i]; | |||||
out[i] += simd::float_4(_mm_and_ps(in2[i].v, channelMask[channels2-4*i].v)); | |||||
for(int c=0; c<channels2; c+=4) out[c/4] += simd::float_4::load(inputs[IN2_INPUT].getVoltages(c)) * mult2; | |||||
} | } | ||||
if(inputs[IN3_INPUT].isConnected()) { | if(inputs[IN3_INPUT].isConnected()) { | ||||
for(int c=0; c<channels3; c+=4) in3[c/4] = simd::float_4::load(inputs[IN3_INPUT].getVoltages(c)) * mult3; | |||||
for(i=0; i<channels3/4; i++) out[i] += in3[i]; | |||||
out[i] += simd::float_4(_mm_and_ps(in3[i].v, channelMask[channels3-4*i].v)); | |||||
for(int c=0; c<channels3; c+=4) out[c/4] += simd::float_4::load(inputs[IN3_INPUT].getVoltages(c)) * mult3; | |||||
} | } | ||||
if(inputs[IN4_INPUT].isConnected()) { | if(inputs[IN4_INPUT].isConnected()) { | ||||
for(int c=0; c<channels4; c+=4) in4[c/4] = simd::float_4::load(inputs[IN4_INPUT].getVoltages(c)) * mult4; | |||||
for(i=0; i<channels4/4; i++) out[i] += in4[i]; | |||||
out[i] += simd::float_4(_mm_and_ps(in4[i].v, channelMask[channels4-4*i].v)); | |||||
for(int c=0; c<channels4; c+=4) out[c/4] += simd::float_4::load(inputs[IN4_INPUT].getVoltages(c)) * mult4; | |||||
} | } | ||||
@@ -120,10 +91,24 @@ struct Mixer : Module { | |||||
out[c / 4] *= minus_one; | out[c / 4] *= minus_one; | ||||
out[c / 4].store(outputs[OUT2_OUTPUT].getVoltages(c)); | out[c / 4].store(outputs[OUT2_OUTPUT].getVoltages(c)); | ||||
} | } | ||||
/* | |||||
lights[OUT_POS_LIGHT].setSmoothBrightness(out / 5.f, args.sampleTime); | |||||
lights[OUT_NEG_LIGHT].setSmoothBrightness(-out / 5.f, args.sampleTime); | |||||
*/ | |||||
if(out_channels==1) { | |||||
float light = outputs[OUT1_OUTPUT].getVoltage(); | |||||
lights[OUT_POS_LIGHT].setSmoothBrightness(light / 5.f, args.sampleTime); | |||||
lights[OUT_NEG_LIGHT].setSmoothBrightness(-light / 5.f, args.sampleTime); | |||||
} else | |||||
{ | |||||
float light = 0.0f; | |||||
for(int c=0; c<out_channels; c++) { | |||||
float tmp = outputs[OUT1_OUTPUT].getVoltage(c); | |||||
light += tmp*tmp; | |||||
} | |||||
light = sqrt(light); | |||||
lights[OUT_POS_LIGHT].setBrightness(0.0f); | |||||
lights[OUT_NEG_LIGHT].setBrightness(0.0f); | |||||
lights[OUT_BLUE_LIGHT].setSmoothBrightness(light / 5.f, args.sampleTime); | |||||
} | |||||
} | } | ||||
}; | }; | ||||
@@ -152,7 +137,7 @@ struct MixerWidget : ModuleWidget { | |||||
addOutput(createOutput<PJ301MPort>(Vec(7, 324), module, Mixer::OUT1_OUTPUT)); | addOutput(createOutput<PJ301MPort>(Vec(7, 324), module, Mixer::OUT1_OUTPUT)); | ||||
addOutput(createOutput<PJ301MPort>(Vec(43, 324), module, Mixer::OUT2_OUTPUT)); | addOutput(createOutput<PJ301MPort>(Vec(43, 324), module, Mixer::OUT2_OUTPUT)); | ||||
addChild(createLight<MediumLight<GreenRedLight>>(Vec(32.7, 310), module, Mixer::OUT_POS_LIGHT)); | |||||
addChild(createLight<MediumLight<RedGreenBlueLight>>(Vec(32.7, 310), module, Mixer::OUT_POS_LIGHT)); | |||||
} | } | ||||
}; | }; | ||||
@@ -1,19 +1,17 @@ | |||||
#include "plugin.hpp" | #include "plugin.hpp" | ||||
#include "simd_mask.hpp" | |||||
#include "simd_input.hpp" | |||||
#include "PulseGenerator_4.hpp" | #include "PulseGenerator_4.hpp" | ||||
#define MAX(a,b) a>b?a:b | |||||
static simd::float_4 shapeDelta(simd::float_4 delta, simd::float_4 tau, float shape) { | static simd::float_4 shapeDelta(simd::float_4 delta, simd::float_4 tau, float shape) { | ||||
simd::float_4 lin = simd::sgn(delta) * 10.f / tau; | simd::float_4 lin = simd::sgn(delta) * 10.f / tau; | ||||
if (shape < 0.f) { | if (shape < 0.f) { | ||||
simd::float_4 log = simd::sgn(delta) * simd::float_4(40.f) / tau / (simd::fabs(delta) + simd::float_4(1.f)); | simd::float_4 log = simd::sgn(delta) * simd::float_4(40.f) / tau / (simd::fabs(delta) + simd::float_4(1.f)); | ||||
return crossfade_4(lin, log, -shape * 0.95f); | |||||
return simd::crossfade(lin, log, -shape * 0.95f); | |||||
} | } | ||||
else { | else { | ||||
simd::float_4 exp = M_E * delta / tau; | simd::float_4 exp = M_E * delta / tau; | ||||
return crossfade_4(lin, exp, shape * 0.90f); | |||||
return simd::crossfade(lin, exp, shape * 0.90f); | |||||
} | } | ||||
} | } | ||||
@@ -76,10 +74,6 @@ struct Rampage : Module { | |||||
NUM_LIGHTS | NUM_LIGHTS | ||||
}; | }; | ||||
/* | |||||
float out[2] = {}; | |||||
bool gate[2] = {}; | |||||
*/ | |||||
simd::float_4 out[2][4]; | simd::float_4 out[2][4]; | ||||
simd::float_4 gate[2][4]; // use simd __m128 logic instead of bool | simd::float_4 gate[2][4]; // use simd __m128 logic instead of bool | ||||
@@ -87,7 +81,7 @@ struct Rampage : Module { | |||||
dsp::TSchmittTrigger<simd::float_4> trigger_4[2][4]; | dsp::TSchmittTrigger<simd::float_4> trigger_4[2][4]; | ||||
PulseGenerator_4 endOfCyclePulse[2][4]; | PulseGenerator_4 endOfCyclePulse[2][4]; | ||||
ChannelMask channelMask; | |||||
// ChannelMask channelMask; | |||||
Rampage() { | Rampage() { | ||||
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); | ||||
@@ -121,15 +115,15 @@ struct Rampage : Module { | |||||
channels_in[part] = inputs[IN_A_INPUT+part].getChannels(); | channels_in[part] = inputs[IN_A_INPUT+part].getChannels(); | ||||
channels_trig[part] = inputs[TRIGG_A_INPUT+part].getChannels(); | channels_trig[part] = inputs[TRIGG_A_INPUT+part].getChannels(); | ||||
channels[part] = MAX(channels_in[part], channels_trig[part]); | |||||
channels[part] = MAX(1, channels[part]); | |||||
channels[part] = std::max(channels_in[part], channels_trig[part]); | |||||
channels[part] = std::max(1, channels[part]); | |||||
outputs[OUT_A_OUTPUT+part].setChannels(channels[part]); | outputs[OUT_A_OUTPUT+part].setChannels(channels[part]); | ||||
outputs[RISING_A_OUTPUT+part].setChannels(channels[part]); | outputs[RISING_A_OUTPUT+part].setChannels(channels[part]); | ||||
outputs[FALLING_A_OUTPUT+part].setChannels(channels[part]); | outputs[FALLING_A_OUTPUT+part].setChannels(channels[part]); | ||||
outputs[EOC_A_OUTPUT+part].setChannels(channels[part]); | outputs[EOC_A_OUTPUT+part].setChannels(channels[part]); | ||||
} | } | ||||
int channels_max = MAX(channels[0], channels[1]); | |||||
int channels_max = std::max(channels[0], channels[1]); | |||||
outputs[COMPARATOR_OUTPUT].setChannels(channels_max); | outputs[COMPARATOR_OUTPUT].setChannels(channels_max); | ||||
outputs[MIN_OUTPUT].setChannels(channels_max); | outputs[MIN_OUTPUT].setChannels(channels_max); | ||||
@@ -174,14 +168,14 @@ struct Rampage : Module { | |||||
if(inputs[IN_A_INPUT + part].isConnected()) { | if(inputs[IN_A_INPUT + part].isConnected()) { | ||||
load_input(inputs[IN_A_INPUT + part], in, channels_in[part]); | load_input(inputs[IN_A_INPUT + part], in, channels_in[part]); | ||||
channelMask.apply_all(in, channels_in[part]); | |||||
// channelMask.apply_all(in, channels_in[part]); | |||||
} else { | } else { | ||||
memset(in, 0, sizeof(in)); | memset(in, 0, sizeof(in)); | ||||
} | } | ||||
if(inputs[TRIGG_A_INPUT + part].isConnected()) { | if(inputs[TRIGG_A_INPUT + part].isConnected()) { | ||||
add_input(inputs[TRIGG_A_INPUT + part], in_trig, channels_trig[part]); | add_input(inputs[TRIGG_A_INPUT + part], in_trig, channels_trig[part]); | ||||
channelMask.apply_all(in_trig, channels_trig[part]); | |||||
// channelMask.apply_all(in_trig, channels_trig[part]); | |||||
} | } | ||||
if(inputs[EXP_CV_A_INPUT + part].isConnected()) { | if(inputs[EXP_CV_A_INPUT + part].isConnected()) { | ||||
@@ -195,7 +189,7 @@ struct Rampage : Module { | |||||
add_input(inputs[RISE_CV_A_INPUT + part], riseCV, channels[part]); | add_input(inputs[RISE_CV_A_INPUT + part], riseCV, channels[part]); | ||||
add_input(inputs[FALL_CV_A_INPUT + part], fallCV, channels[part]); | add_input(inputs[FALL_CV_A_INPUT + part], fallCV, channels[part]); | ||||
add_input(inputs[CYCLE_A_INPUT+part], cycle, channels[part]); | add_input(inputs[CYCLE_A_INPUT+part], cycle, channels[part]); | ||||
channelMask.apply(cycle, channels[part]); // check whether this is necessary | |||||
// channelMask.apply(cycle, channels[part]); // check whether this is necessary | |||||
// start processing: | // start processing: | ||||
@@ -272,61 +266,9 @@ struct Rampage : Module { | |||||
lights[OUT_A_LIGHT + 3*part+2].setBrightness(10.0f); | lights[OUT_A_LIGHT + 3*part+2].setBrightness(10.0f); | ||||
} | } | ||||
// Integrator | |||||
// bool rising = false; | |||||
// bool falling = false; | |||||
/* | |||||
if (delta > 0) { | |||||
// Rise | |||||
float riseCv = params[RISE_A_PARAM + c].getValue() - inputs[EXP_CV_A_INPUT + c].getVoltage() / 10.0 + inputs[RISE_CV_A_INPUT + c].getVoltage() / 10.0; | |||||
riseCv = clamp(riseCv, 0.0f, 1.0f); | |||||
float rise = minTime * std::pow(2.0, riseCv * 10.0); | |||||
out[c] += shapeDelta(delta, rise, shape) * args.sampleTime; | |||||
rising = (in - out[c] > 1e-3); | |||||
if (!rising) { | |||||
gate[c] = false; | |||||
} | |||||
} | |||||
else if (delta < 0) { | |||||
// Fall | |||||
float fallCv = params[FALL_A_PARAM + c].getValue() - inputs[EXP_CV_A_INPUT + c].getVoltage() / 10.0 + inputs[FALL_CV_A_INPUT + c].getVoltage() / 10.0; | |||||
fallCv = clamp(fallCv, 0.0f, 1.0f); | |||||
float fall = minTime * std::pow(2.0, fallCv * 10.0); | |||||
out[c] += shapeDelta(delta, fall, shape) * args.sampleTime; | |||||
falling = (in - out[c] < -1e-3); | |||||
if (!falling) { | |||||
// End of cycle, check if we should turn the gate back on (cycle mode) | |||||
endOfCyclePulse[c].trigger(1e-3); | |||||
if (params[CYCLE_A_PARAM + c].getValue() * 10.0 + inputs[CYCLE_A_INPUT + c].getVoltage() >= 4.0) { | |||||
gate[c] = true; | |||||
} | |||||
} | |||||
} | |||||
else { | |||||
gate[c] = false; | |||||
} | |||||
if (!rising && !falling) { | |||||
out[c] = in; | |||||
} | |||||
*/ | |||||
// outputs[RISING_A_OUTPUT + part].setVoltage((rising ? 10.0 : 0.0)); | |||||
// outputs[FALLING_A_OUTPUT + part].setVoltage((falling ? 10.0 : 0.0)); | |||||
// lights[RISING_A_LIGHT + part].setSmoothBrightness(rising ? 1.0 : 0.0, args.sampleTime); | |||||
// lights[FALLING_A_LIGHT + part].setSmoothBrightness(falling ? 1.0 : 0.0, args.sampleTime); | |||||
// outputs[EOC_A_OUTPUT + part].setVoltage((endOfCyclePulse[c].process(args.sampleTime) ? 10.0 : 0.0)); | |||||
// outputs[OUT_A_OUTPUT + part].setVoltage(out[c]); | |||||
// lights[OUT_A_LIGHT + part].setSmoothBrightness(out[c] / 10.0, args.sampleTime); | |||||
} // for (int part, ... ) | } // for (int part, ... ) | ||||
// Logic | // Logic | ||||
float balance = params[BALANCE_PARAM].getValue(); | float balance = params[BALANCE_PARAM].getValue(); | ||||
@@ -1,5 +1,5 @@ | |||||
#include "plugin.hpp" | #include "plugin.hpp" | ||||
#include "simd_mask.hpp" | |||||
#include "simd_input.hpp" | |||||
struct SlewLimiter : Module { | struct SlewLimiter : Module { | ||||
@@ -21,8 +21,6 @@ struct SlewLimiter : Module { | |||||
}; | }; | ||||
simd::float_4 out[4]; | simd::float_4 out[4]; | ||||
ChannelMask channelMask; | |||||
SlewLimiter() { | SlewLimiter() { | ||||
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS); | config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS); | ||||
@@ -42,7 +40,7 @@ struct SlewLimiter : Module { | |||||
int channels = inputs[IN_INPUT].getChannels(); | int channels = inputs[IN_INPUT].getChannels(); | ||||
// minimum and maximum slopes in volts per second | |||||
// minimum and std::maximum slopes in volts per second | |||||
const float slewMin = 0.1; | const float slewMin = 0.1; | ||||
const float slewMax = 10000.f; | const float slewMax = 10000.f; | ||||
// Amount of extra slew per voltage difference | // Amount of extra slew per voltage difference | ||||
@@ -55,9 +53,9 @@ struct SlewLimiter : Module { | |||||
outputs[OUT_OUTPUT].setChannels(channels); | outputs[OUT_OUTPUT].setChannels(channels); | ||||
load_input(inputs[IN_INPUT], in, channels); channelMask.apply(in, channels); | |||||
load_input(inputs[RISE_INPUT], riseCV, channels); channelMask.apply(riseCV, channels); | |||||
load_input(inputs[FALL_INPUT], fallCV, channels); channelMask.apply(fallCV, channels); | |||||
load_input(inputs[IN_INPUT], in, channels); | |||||
load_input(inputs[RISE_INPUT], riseCV, channels); | |||||
load_input(inputs[FALL_INPUT], fallCV, channels); | |||||
for(int c=0; c<channels; c+=4) { | for(int c=0; c<channels; c+=4) { | ||||
riseCV[c/4] += param_rise; | riseCV[c/4] += param_rise; | ||||
@@ -73,38 +71,12 @@ struct SlewLimiter : Module { | |||||
simd::float_4 slew = slewMax * simd::pow(slewMin / slewMax, rateCV); | simd::float_4 slew = slewMax * simd::pow(slewMin / slewMax, rateCV); | ||||
out[c/4] += slew * crossfade_4(simd::float_4(1.0f), shapeScale*delta, shape) * args.sampleTime; | |||||
out[c/4] += slew * simd::crossfade(simd::float_4(1.0f), shapeScale*delta, shape) * args.sampleTime; | |||||
out[c/4] = ifelse( delta_gt_0 & (out[c/4]>in[c/4]), in[c/4], out[c/4]); | out[c/4] = ifelse( delta_gt_0 & (out[c/4]>in[c/4]), in[c/4], out[c/4]); | ||||
out[c/4] = ifelse( delta_lt_0 & (out[c/4]<in[c/4]), in[c/4], out[c/4]); | out[c/4] = ifelse( delta_lt_0 & (out[c/4]<in[c/4]), in[c/4], out[c/4]); | ||||
out[c/4].store(outputs[OUT_OUTPUT].getVoltages(c)); | out[c/4].store(outputs[OUT_OUTPUT].getVoltages(c)); | ||||
} | } | ||||
/* | |||||
for(int c=0; c<channels; c++) { | |||||
float in = inputs[IN_INPUT].getVoltage(c); | |||||
// Rise | |||||
if (in > out[c]) { | |||||
float rise = inputs[RISE_INPUT].getPolyVoltage(c) / 10.f + param_rise; | |||||
float slew = slewMax * std::pow(slewMin / slewMax, rise); | |||||
out[c] += slew * crossfade(1.f, shapeScale * (in - out[c]), shape) * args.sampleTime; | |||||
if (out[c] > in) | |||||
out[c] = in; | |||||
} | |||||
// Fall | |||||
else if (in < out[c]) { | |||||
float fall = inputs[FALL_INPUT].getPolyVoltage(c) / 10.f + param_fall; | |||||
float slew = slewMax * std::pow(slewMin / slewMax, fall); | |||||
out[c] -= slew * crossfade(1.f, shapeScale * (out[c] - in), shape) * args.sampleTime; | |||||
if (out[c] < in) | |||||
out[c] = in; | |||||
} | |||||
} | |||||
outputs[OUT_OUTPUT].writeVoltages(out); | |||||
*/ | |||||
} | } | ||||
}; | }; | ||||
@@ -0,0 +1,24 @@ | |||||
#pragma once | |||||
#include "rack.hpp" | |||||
inline void load_input(Input &in, simd::float_4 *v, int numChannels) { | |||||
int inChannels = in.getChannels(); | |||||
if(inChannels==1) { | |||||
for(int i=0; i<numChannels; i++) v[i] = simd::float_4(in.getVoltage()); | |||||
} else { | |||||
for(int c=0; c<inChannels; c+=4) v[c/4] = simd::float_4::load(in.getVoltages(c)); | |||||
} | |||||
} | |||||
inline void add_input(Input &in, simd::float_4 *v, int numChannels) { | |||||
int inChannels = in.getChannels(); | |||||
if(inChannels==1) { | |||||
for(int i=0; i<numChannels; i++) v[i] += simd::float_4(in.getVoltage()); | |||||
} else { | |||||
for(int c=0; c<inChannels; c+=4) v[c/4] += simd::float_4::load(in.getVoltages(c)); | |||||
} | |||||
} | |||||
@@ -1,61 +0,0 @@ | |||||
#pragma once | |||||
#include "rack.hpp" | |||||
struct ChannelMask { | |||||
rack::simd::float_4 mask[4]; | |||||
ChannelMask() { | |||||
__m128i tmp = _mm_cmpeq_epi16(_mm_set_epi32(0,0,0,0),_mm_set_epi32(0,0,0,0)); | |||||
for(int i=0; i<4; i++) { | |||||
mask[3-i] = simd::float_4(_mm_castsi128_ps(tmp)); | |||||
tmp = _mm_srli_si128(tmp, 4); | |||||
} | |||||
}; | |||||
~ChannelMask() {}; | |||||
inline const rack::simd::float_4 operator[](const int c) {return mask[c];} | |||||
inline void apply(simd::float_4 *vec, int numChannels) { | |||||
int c=numChannels/4; | |||||
if(c<4) vec[c] = vec[c]&mask[numChannels-4*c]; | |||||
} | |||||
inline void apply_all(simd::float_4 *vec, int numChannels) { | |||||
int c=numChannels/4; | |||||
if(c<4) { | |||||
vec[c] = vec[c]&mask[numChannels-4*c]; | |||||
for(int i=c+1; i<4; i++) vec[i] = simd::float_4::zero(); | |||||
} | |||||
} | |||||
}; | |||||
inline void load_input(Input &in, simd::float_4 *v, int numChannels) { | |||||
int inChannels = in.getChannels(); | |||||
if(inChannels==1) { | |||||
for(int i=0; i<numChannels; i++) v[i] = simd::float_4(in.getVoltage()); | |||||
} else { | |||||
for(int c=0; c<inChannels; c+=4) v[c/4] = simd::float_4::load(in.getVoltages(c)); | |||||
} | |||||
} | |||||
inline void add_input(Input &in, simd::float_4 *v, int numChannels) { | |||||
int inChannels = in.getChannels(); | |||||
if(inChannels==1) { | |||||
for(int i=0; i<numChannels; i++) v[i] += simd::float_4(in.getVoltage()); | |||||
} else { | |||||
for(int c=0; c<inChannels; c+=4) v[c/4] += simd::float_4::load(in.getVoltages(c)); | |||||
} | |||||
} | |||||
inline simd::float_4 crossfade_4(simd::float_4 a, simd::float_4 b, simd::float_4 p) { | |||||
return a + (b - a) * p; | |||||
} |