Signed-off-by: hemmer <915048+hemmer@users.noreply.github.com>tags/v1.1.0^2
@@ -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,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); | ||||
@@ -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)); | |||||
} | |||||
} | } | ||||
}; | }; | ||||
@@ -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)); | |||||
} | } | ||||
@@ -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]) { | ||||
@@ -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)); | |||||
} | |||||
} | |||||