Browse Source

interim commit

Signed-off-by: hemmer <915048+hemmer@users.noreply.github.com>
tags/v1.1.0^2
Martin hemmer 5 years ago
parent
commit
fe97947a56
6 changed files with 285 additions and 102 deletions
  1. +20
    -23
      src/ABC.cpp
  2. +1
    -1
      src/DualAtenuverter.cpp
  3. +181
    -62
      src/EvenVCO.cpp
  4. +8
    -11
      src/Mixer.cpp
  5. +29
    -5
      src/Rampage.cpp
  6. +46
    -0
      src/simd_mask.hpp

+ 20
- 23
src/ABC.cpp View File

@@ -1,4 +1,5 @@
#include "plugin.hpp" #include "plugin.hpp"
#include "simd_mask.hpp"


#define MAX(a,b) (a>b)?a:b #define MAX(a,b) (a>b)?a:b


@@ -65,7 +66,9 @@ struct ABC : Module {
NUM_LIGHTS NUM_LIGHTS
}; };


simd::float_4 mask[4];
// simd::float_4 mask[4];
ChannelMask channelMask;




ABC() { ABC() {
@@ -75,27 +78,19 @@ struct ABC : Module {
configParam(B2_LEVEL_PARAM, -1.0, 1.0, 0.0, "B2 Level"); configParam(B2_LEVEL_PARAM, -1.0, 1.0, 0.0, "B2 Level");
configParam(C2_LEVEL_PARAM, -1.0, 1.0, 0.0, "C2 Level"); configParam(C2_LEVEL_PARAM, -1.0, 1.0, 0.0, "C2 Level");


/*
__m128i tmp = _mm_cmpeq_epi16(_mm_set_epi32(0,0,0,0),_mm_set_epi32(0,0,0,0)); __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++) { for(int i=0; i<4; i++) {
mask[3-i] = simd::float_4(_mm_castsi128_ps(tmp)); mask[3-i] = simd::float_4(_mm_castsi128_ps(tmp));
tmp = _mm_srli_si128(tmp, 4); tmp = _mm_srli_si128(tmp, 4);
} }
*/


} }


inline void load_input(Input &in, simd::float_4 *v, int numChannels) {
if(numChannels==1) {
for(int i=0; i<4; i++) v[i] = simd::float_4(in.getVoltage());
} else {
for(int c=0; c<numChannels; c+=4) v[c/4] = simd::float_4::load(in.getVoltages(c));
}
}


inline void crop_channels(simd::float_4 *vec, int numChannels) {
int c=numChannels/4;
vec[c] = simd::float_4(_mm_and_ps(vec[c].v, mask[numChannels-4*c].v));
}



void process(const ProcessArgs &args) override { void process(const ProcessArgs &args) override {


@@ -123,7 +118,7 @@ struct ABC : Module {
channels_1 = MAX(channels_1, channels_B1); channels_1 = MAX(channels_1, channels_B1);
channels_1 = MAX(channels_1, channels_C1); channels_1 = MAX(channels_1, channels_C1);


int channels_2 = channels_1;
int channels_2 = 1;
channels_2 = MAX(channels_2, channels_A2); channels_2 = MAX(channels_2, channels_A2);
channels_2 = MAX(channels_2, channels_B2); channels_2 = MAX(channels_2, channels_B2);
channels_2 = MAX(channels_2, channels_C2); channels_2 = MAX(channels_2, channels_C2);
@@ -136,7 +131,7 @@ struct ABC : Module {




load_input(inputs[A1_INPUT], a1, channels_A1); load_input(inputs[A1_INPUT], a1, channels_A1);
crop_channels(a1, channels_1);
channelMask.apply(a1, channels_1);


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);
@@ -144,7 +139,7 @@ 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);
} }
crop_channels(b1, channels_1);
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);
@@ -152,14 +147,14 @@ 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);
} }
crop_channels(c1, channels_1);
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]);






load_input(inputs[A1_INPUT], a1, channels_A1);
crop_channels(a1, channels_1);
load_input(inputs[A2_INPUT], a2, channels_A2);
channelMask.apply(a2, channels_2);


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);
@@ -167,7 +162,7 @@ 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);
} }
crop_channels(b2, channels_2);
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);
@@ -175,7 +170,7 @@ 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);
} }
crop_channels(c2, channels_2);
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]);


@@ -188,10 +183,12 @@ 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);

} }
if (outputs[OUT2_OUTPUT].isConnected()) { if (outputs[OUT2_OUTPUT].isConnected()) {
outputs[OUT2_OUTPUT].setChannels(channels_1);
for(int c=0; c<channels_1; c+=4) out2[c/4].store(outputs[OUT2_OUTPUT].getVoltages(c));
outputs[OUT2_OUTPUT].setChannels(channels_2);
for(int c=0; c<channels_2; c+=4) out2[c/4].store(outputs[OUT2_OUTPUT].getVoltages(c));
} }


// Lights // Lights


+ 1
- 1
src/DualAtenuverter.cpp View File

@@ -1,4 +1,5 @@
#include "plugin.hpp" #include "plugin.hpp"
#include "simd_mask.hpp"




struct DualAtenuverter : Module { struct DualAtenuverter : Module {
@@ -49,7 +50,6 @@ struct DualAtenuverter : Module {
simd::float_4 offset1 = simd::float_4(params[OFFSET1_PARAM].getValue()); simd::float_4 offset1 = simd::float_4(params[OFFSET1_PARAM].getValue());
simd::float_4 offset2 = simd::float_4(params[OFFSET2_PARAM].getValue()); simd::float_4 offset2 = simd::float_4(params[OFFSET2_PARAM].getValue());



for (int c = 0; c < channels1; c += 4) out1[c / 4] = clamp(simd::float_4::load(inputs[IN1_INPUT].getVoltages(c)) * att1 + offset1, -10.f, 10.f); for (int c = 0; c < channels1; c += 4) out1[c / 4] = clamp(simd::float_4::load(inputs[IN1_INPUT].getVoltages(c)) * att1 + offset1, -10.f, 10.f);
for (int c = 0; c < channels2; c += 4) out2[c / 4] = clamp(simd::float_4::load(inputs[IN2_INPUT].getVoltages(c)) * att2 + offset2, -10.f, 10.f); for (int c = 0; c < channels2; c += 4) out2[c / 4] = clamp(simd::float_4::load(inputs[IN2_INPUT].getVoltages(c)) * att2 + offset2, -10.f, 10.f);


+ 181
- 62
src/EvenVCO.cpp View File

@@ -1,4 +1,5 @@
#include "plugin.hpp" #include "plugin.hpp"
#include "simd_mask.hpp"


#define MAX(a,b) (a>b)?a:b #define MAX(a,b) (a>b)?a:b


@@ -26,38 +27,73 @@ struct EvenVCO : Module {
NUM_OUTPUTS NUM_OUTPUTS
}; };


float phase = 0.0;
simd::float_4 phase[4];
simd::float_4 tri[4];

/** The value of the last sync input */ /** The value of the last sync input */
float sync = 0.0; float sync = 0.0;
/** The outputs */ /** The outputs */
float tri = 0.0;
/** Whether we are past the pulse width already */ /** Whether we are past the pulse width already */
bool halfPhase = false;
bool halfPhase[PORT_MAX_CHANNELS];


dsp::MinBlepGenerator<16, 32> triSquareMinBlep;
dsp::MinBlepGenerator<16, 32> triMinBlep;
dsp::MinBlepGenerator<16, 32> sineMinBlep;
dsp::MinBlepGenerator<16, 32> doubleSawMinBlep;
dsp::MinBlepGenerator<16, 32> sawMinBlep;
dsp::MinBlepGenerator<16, 32> squareMinBlep;
dsp::MinBlepGenerator<16, 32> triSquareMinBlep[PORT_MAX_CHANNELS];
dsp::MinBlepGenerator<16, 32> triMinBlep[PORT_MAX_CHANNELS];
dsp::MinBlepGenerator<16, 32> sineMinBlep[PORT_MAX_CHANNELS];
dsp::MinBlepGenerator<16, 32> doubleSawMinBlep[PORT_MAX_CHANNELS];
dsp::MinBlepGenerator<16, 32> sawMinBlep[PORT_MAX_CHANNELS];
dsp::MinBlepGenerator<16, 32> squareMinBlep[PORT_MAX_CHANNELS];


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);
configParam(TUNE_PARAM, -7.0, 7.0, 0.0, "Tune", " semitones"); configParam(TUNE_PARAM, -7.0, 7.0, 0.0, "Tune", " semitones");
configParam(PWM_PARAM, -1.0, 1.0, 0.0, "Pulse width"); configParam(PWM_PARAM, -1.0, 1.0, 0.0, "Pulse width");
for(int i=0; i<4; i++) {
phase[i] = simd::float_4(0.0f);
tri[i] = simd::float_4(0.0f);
}
for(int c=0; c<PORT_MAX_CHANNELS; c++) halfPhase[c] = false;
}


/*
inline void load_input(Input &in, simd::float_4 *v, int numChannels) {
if(numChannels==1) {
for(int i=0; i<4; i++) v[i] = simd::float_4(in.getVoltage());
} else {
for(int c=0; c<numChannels; c+=4) v[c/4] = simd::float_4::load(in.getVoltages(c));
}
}
*/


inline void add_input(Input &in, simd::float_4 *v, int numChannels) {
if(numChannels==1) {
for(int i=0; i<4; i++) v[i] = simd::float_4(in.getVoltage());
} else {
for(int c=0; c<numChannels; c+=4) v[c/4] = simd::float_4::load(in.getVoltages(c));
}
} }


void process(const ProcessArgs &args) override { void process(const ProcessArgs &args) override {
// Compute frequency, pitch is 1V/oct

simd::float_4 pitch[4];
simd::float_4 pitch_1[4];
simd::float_4 pitch_2[4];
simd::float_4 pitch_fm[4];
simd::float_4 freq[4];
simd::float_4 pw[4];
simd::float_4 pwm[4];
simd::float_4 deltaPhase[4];
simd::float_4 oldPhase[4];


int channels_pitch1 = inputs[PITCH1_INPUT].getChannels(); int channels_pitch1 = inputs[PITCH1_INPUT].getChannels();
int channels_pitch2 = inputs[PITCH2_INPUT].getChannels(); int channels_pitch2 = inputs[PITCH2_INPUT].getChannels();
int channels_fm = inputs[FM_INPUT].getChannels(); int channels_fm = inputs[FM_INPUT].getChannels();
int channels_pwm = inputs[PWM_INPUT].getChannels();


int channels = 1; int channels = 1;
channels = MAX(channels, channels_pitch1); channels = MAX(channels, channels_pitch1);
@@ -66,68 +102,151 @@ struct EvenVCO : Module {


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;


// Compute frequency, pitch is 1V/oct

for(int c=0; c<channels; c+=4) pitch[c/4] = simd::float_4(pitch_0);

if(inputs[PITCH1_INPUT].isConnected()) {
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];
}

if(inputs[PITCH2_INPUT].isConnected()) {
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];
}

if(inputs[FM_INPUT].isConnected()) {
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; c+=4) {
freq[c/4] = dsp::FREQ_C4 * simd::pow(2.f, pitch[c/4]);
freq[c/4] = clamp(freq[c/4], 0.f, 20000.f);
}


pitch += inputs[PITCH1_INPUT].getVoltage() + inputs[PITCH2_INPUT].getVoltage();
pitch += inputs[FM_INPUT].getVoltage() / 4.f;
float freq = dsp::FREQ_C4 * std::pow(2.f, pitch);
freq = clamp(freq, 0.f, 20000.f);


// Pulse width // Pulse width
float pw = params[PWM_PARAM].getValue() + inputs[PWM_INPUT].getVoltage() / 5.f;
const float minPw = 0.05;
pw = rescale(clamp(pw, -1.f, 1.f), -1.f, 1.f, minPw, 1.f - minPw);

// Advance phase
float deltaPhase = clamp(freq * args.sampleTime, 1e-6f, 0.5f);
float oldPhase = phase;
phase += deltaPhase;

if (oldPhase < 0.5 && phase >= 0.5) {
float crossing = -(phase - 0.5) / deltaPhase;
triSquareMinBlep.insertDiscontinuity(crossing, 2.f);
doubleSawMinBlep.insertDiscontinuity(crossing, -2.f);

float pw_0 = params[PWM_PARAM].getValue();

for(int c=0; c<channels; c+=4) pw[c/4] = simd::float_4(pw_0);
if(inputs[PWM_INPUT].isConnected()) {
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;
} }


if (!halfPhase && phase >= pw) {
float crossing = -(phase - pw) / deltaPhase;
squareMinBlep.insertDiscontinuity(crossing, 2.f);
halfPhase = true;
const simd::float_4 minPw_4 = simd::float_4(0.05f);
const simd::float_4 m_one_4 = simd::float_4(-1.0f);
const simd::float_4 one_4 = simd::float_4(1.0f);

for(int c=0; c<channels; c+=4) {
pw[c/4] = rescale(clamp(pw[c/4], m_one_4, one_4), m_one_4, one_4, minPw_4, one_4 - minPw_4);

// Advance phase
deltaPhase[c/4] = clamp(freq[c/4] * args.sampleTime, simd::float_4(1e-6f), simd::float_4(0.5f));
oldPhase[c/4] = phase[c/4];
phase[c/4] += deltaPhase[c/4];
}

// the next block can't be done with SIMD instructions:

for(int c=0; c<channels; c++) {

if (oldPhase[c/4].s[c%4] < 0.5 && phase[c/4].s[c%4] >= 0.5) {
float crossing = -(phase[c/4].s[c%4] - 0.5) / deltaPhase[c/4].s[c%4];
triSquareMinBlep[c].insertDiscontinuity(crossing, 2.f);
doubleSawMinBlep[c].insertDiscontinuity(crossing, -2.f);
}

if (!halfPhase[c] && phase[c/4].s[c%4] >= pw[c/4].s[c%4]) {
float crossing = -(phase[c/4].s[c%4] - pw[c/4].s[c%4]) / deltaPhase[c/4].s[c%4];
squareMinBlep[c].insertDiscontinuity(crossing, 2.f);
halfPhase[c] = true;
}

// Reset phase if at end of cycle
if (phase[c/4].s[c%4] >= 1.f) {
phase[c/4].s[c%4] -= 1.f;
float crossing = -phase[c/4].s[c%4] / deltaPhase[c/4].s[c%4];
triSquareMinBlep[c].insertDiscontinuity(crossing, -2.f);
doubleSawMinBlep[c].insertDiscontinuity(crossing, -2.f);
squareMinBlep[c].insertDiscontinuity(crossing, -2.f);
sawMinBlep[c].insertDiscontinuity(crossing, -2.f);
halfPhase[c] = false;
}
} }


// Reset phase if at end of cycle
if (phase >= 1.f) {
phase -= 1.f;
float crossing = -phase / deltaPhase;
triSquareMinBlep.insertDiscontinuity(crossing, -2.f);
doubleSawMinBlep.insertDiscontinuity(crossing, -2.f);
squareMinBlep.insertDiscontinuity(crossing, -2.f);
sawMinBlep.insertDiscontinuity(crossing, -2.f);
halfPhase = false;
simd::float_4 triSquareMinBlepOut[4];
simd::float_4 doubleSawMinBlepOut[4];
simd::float_4 sawMinBlepOut[4];
simd::float_4 squareMinBlepOut[4];

simd::float_4 triSquare[4];
simd::float_4 sine[4];
simd::float_4 doubleSaw[4];

simd::float_4 even[4];
simd::float_4 saw[4];
simd::float_4 square[4];
simd::float_4 triOut[4];

for(int c=0; c<channels; c++) {
triSquareMinBlepOut[c/4].s[c%4] = triSquareMinBlep[c].process();
doubleSawMinBlepOut[c/4].s[c%4] = doubleSawMinBlep[c].process();
sawMinBlepOut[c/4].s[c%4] = sawMinBlep[c].process();
squareMinBlepOut[c/4].s[c%4] = squareMinBlep[c].process();
} }


// Outputs // Outputs
float triSquare = (phase < 0.5) ? -1.f : 1.f;
triSquare += triSquareMinBlep.process();

// Integrate square for triangle
tri += 4.f * triSquare * freq * args.sampleTime;
tri *= (1.f - 40.f * args.sampleTime);

float sine = -std::cos(2*M_PI * phase);
float doubleSaw = (phase < 0.5) ? (-1.f + 4.f*phase) : (-1.f + 4.f*(phase - 0.5));
doubleSaw += doubleSawMinBlep.process();
float even = 0.55 * (doubleSaw + 1.27 * sine);
float saw = -1.f + 2.f*phase;
saw += sawMinBlep.process();
float square = (phase < pw) ? -1.f : 1.f;
square += squareMinBlep.process();

// Set outputs
outputs[TRI_OUTPUT].setVoltage(5.f*tri);
outputs[SINE_OUTPUT].setVoltage(5.f*sine);
outputs[EVEN_OUTPUT].setVoltage(5.f*even);
outputs[SAW_OUTPUT].setVoltage(5.f*saw);
outputs[SQUARE_OUTPUT].setVoltage(5.f*square);

outputs[TRI_OUTPUT].setChannels(channels);
outputs[SINE_OUTPUT].setChannels(channels);
outputs[EVEN_OUTPUT].setChannels(channels);
outputs[SAW_OUTPUT].setChannels(channels);
outputs[SQUARE_OUTPUT].setChannels(channels);

for(int c=0; c<channels; c+=4) {
triSquare[c/4] = simd::ifelse( (phase[c/4] < 0.5f*one_4), m_one_4, one_4);
triSquare[c/4] += triSquareMinBlepOut[c/4];

// Integrate square for triangle
tri[c/4] += (4.f * triSquare[c/4]) * (freq[c/4] * args.sampleTime);
tri[c/4] *= (1.f - 40.f * args.sampleTime);
triOut[c/4] = 5.f * tri[c/4];


sine[c/4] = 5.f * simd::cos(2*M_PI * phase[c/4]);
doubleSaw[c/4] = simd::ifelse( (phase[c/4] < 0.5), (-1.f + 4.f*phase[c/4]), (-1.f + 4.f*(phase[c/4] - 0.5f)));
doubleSaw[c/4] += doubleSawMinBlepOut[c/4];
doubleSaw[c/4] *= 5.f;

even[c/4] = 0.55 * (doubleSaw[c/4] + 1.27 * sine[c/4]);
saw[c/4] = -1.f + 2.f*phase[c/4];
saw[c/4] += sawMinBlepOut[c/4];
saw[c/4] *= 5.f;

square[c/4] = simd::ifelse( (phase[c/4] < pw[c/4]), m_one_4, one_4) ;
square[c/4] += squareMinBlepOut[c/4];
square[c/4] *= 5.f;

// Set outputs

triOut[c/4].store(outputs[TRI_OUTPUT].getVoltages(c));
sine[c/4].store(outputs[SINE_OUTPUT].getVoltages(c));
even[c/4].store(outputs[EVEN_OUTPUT].getVoltages(c));
saw[c/4].store(outputs[SAW_OUTPUT].getVoltages(c));
square[c/4].store(outputs[SQUARE_OUTPUT].getVoltages(c));
}
} }
}; };




+ 8
- 11
src/Mixer.cpp View File

@@ -1,4 +1,6 @@
#include "plugin.hpp" #include "plugin.hpp"
#include "simd_mask.hpp"



#define MAX(a,b) (a>b)?a:b #define MAX(a,b) (a>b)?a:b
#define MIN(a,b) (a<b)?a:b #define MIN(a,b) (a<b)?a:b
@@ -30,9 +32,10 @@ struct Mixer : Module {
NUM_LIGHTS NUM_LIGHTS
}; };


simd::float_4 mask[4];
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);
@@ -42,12 +45,6 @@ struct Mixer : Module {


minus_one = simd::float_4(-1.0f); minus_one = simd::float_4(-1.0f);


__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);
}


} }


@@ -90,28 +87,28 @@ struct Mixer : Module {
for(int c=0; c<channels1; c+=4) in1[c/4] = simd::float_4::load(inputs[IN1_INPUT].getVoltages(c)) * mult1; 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. 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, mask[channels1-4*i].v)); // make sure we zero out spurious channels
out[i] += simd::float_4(_mm_and_ps(in1[i].v, channelMask[channels1-4*i].v)); // make sure we zero out spurious channels
} }
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(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]; for(i=0; i<channels2/4; i++) out[i] += in2[i];
out[i] += simd::float_4(_mm_and_ps(in2[i].v, mask[channels2-4*i].v));
out[i] += simd::float_4(_mm_and_ps(in2[i].v, channelMask[channels2-4*i].v));
} }


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(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]; for(i=0; i<channels3/4; i++) out[i] += in3[i];
out[i] += simd::float_4(_mm_and_ps(in3[i].v, mask[channels3-4*i].v));
out[i] += simd::float_4(_mm_and_ps(in3[i].v, channelMask[channels3-4*i].v));
} }


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(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]; for(i=0; i<channels4/4; i++) out[i] += in4[i];
out[i] += simd::float_4(_mm_and_ps(in4[i].v, mask[channels4-4*i].v));
out[i] += simd::float_4(_mm_and_ps(in4[i].v, channelMask[channels4-4*i].v));
} }






+ 29
- 5
src/Rampage.cpp View File

@@ -1,4 +1,5 @@
#include "plugin.hpp" #include "plugin.hpp"
#include "simd_mask.hpp"




static float shapeDelta(float delta, float tau, float shape) { static float shapeDelta(float delta, float tau, float shape) {
@@ -73,10 +74,18 @@ struct Rampage : Module {
NUM_LIGHTS NUM_LIGHTS
}; };


/*
float out[2] = {}; float out[2] = {};
bool gate[2] = {}; bool gate[2] = {};
dsp::SchmittTrigger trigger[2];
dsp::PulseGenerator endOfCyclePulse[2];
*/

simd::float_4 out[2][4];
simd::int32_4 gate[2][4]; // represent bool as integer: false = 0; true > o0

dsp::SchmittTrigger trigger[2, PORT_MAX_CHANNELS];
dsp::PulseGenerator endOfCyclePulse[2, PORT_MAX_CHANNELS];

ChannelMask channelMask;


Rampage() { Rampage() {
config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS); config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS, NUM_LIGHTS);
@@ -93,12 +102,27 @@ struct Rampage : Module {
configParam(FALL_B_PARAM, 0.0, 1.0, 0.0, "Ch 2 fall time"); configParam(FALL_B_PARAM, 0.0, 1.0, 0.0, "Ch 2 fall time");
configParam(CYCLE_B_PARAM, 0.0, 1.0, 0.0, "Ch 2 cycle"); configParam(CYCLE_B_PARAM, 0.0, 1.0, 0.0, "Ch 2 cycle");
configParam(BALANCE_PARAM, 0.0, 1.0, 0.5, "Balance"); configParam(BALANCE_PARAM, 0.0, 1.0, 0.5, "Balance");

memset(out, 0, sizeof(out));
memset(gate, 0, sizeof(gate));
} }


void process(const ProcessArgs &args) override { void process(const ProcessArgs &args) override {
for (int c = 0; c < 2; c++) {
float in = inputs[IN_A_INPUT + c].getVoltage();
if (trigger[c].process(params[TRIGG_A_PARAM + c].getValue() * 10.0 + inputs[TRIGG_A_INPUT + c].getVoltage() / 2.0)) {

int channels_in_A[2];
int channels_in_B[2];

for (int part=0; part<2; part++) {
channels_in_A[part] = inputs[IN_A_INPUT].getChannels()
channels_in_B[part] = inputs[IN_B_INPUT].getChannels()
}

for (int part = 0; part < 2; part++) {
simd::float_4 in[4];

load_input(inputs[IN_A_INPUT + part], in, channels_in_A[part]);

if (trigger[part].process(params[TRIGG_A_PARAM + part].getValue() * 10.0 + inputs[TRIGG_A_INPUT + part].getVoltage() / 2.0)) {
gate[c] = true; gate[c] = true;
} }
if (gate[c]) { if (gate[c]) {


+ 46
- 0
src/simd_mask.hpp View File

@@ -0,0 +1,46 @@
#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;
vec[c] = vec[c]&mask[numChannels-4*c];
}

inline void apply_all(simd::float_4 *vec, int numChannels) {
int c=numChannels/4;
vec[c] = vec[c]&mask[numChannels-4*c];
for(int i=c+1; i<4; i++) vec[i] = simd::float_4(0.f);
}


};

inline void load_input(Input &in, simd::float_4 *v, int numChannels) {
if(numChannels==1) {
for(int i=0; i<4; i++) v[i] = simd::float_4(in.getVoltage());
} else {
for(int c=0; c<numChannels; c+=4) v[c/4] = simd::float_4::load(in.getVoltages(c));
}
}


Loading…
Cancel
Save