diff --git a/src/ABC.cpp b/src/ABC.cpp index 774f8d3..2d02464 100644 --- a/src/ABC.cpp +++ b/src/ABC.cpp @@ -1,4 +1,5 @@ #include "plugin.hpp" +#include "simd_mask.hpp" #define MAX(a,b) (a>b)?a:b @@ -65,7 +66,9 @@ struct ABC : Module { NUM_LIGHTS }; - simd::float_4 mask[4]; + // simd::float_4 mask[4]; + + ChannelMask channelMask; ABC() { @@ -75,27 +78,19 @@ struct ABC : Module { configParam(B2_LEVEL_PARAM, -1.0, 1.0, 0.0, "B2 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)); - + for(int i=0; i<4; i++) { mask[3-i] = simd::float_4(_mm_castsi128_ps(tmp)); 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; cb)?a:b @@ -26,38 +27,73 @@ struct EvenVCO : Module { NUM_OUTPUTS }; - float phase = 0.0; + simd::float_4 phase[4]; + simd::float_4 tri[4]; + /** The value of the last sync input */ float sync = 0.0; /** The outputs */ - float tri = 0.0; /** 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; + ChannelMask channelMask; + EvenVCO() { config(NUM_PARAMS, NUM_INPUTS, NUM_OUTPUTS); configParam(OCTAVE_PARAM, -5.0, 4.0, 0.0, "Octave", "'", 0.5); configParam(TUNE_PARAM, -7.0, 7.0, 0.0, "Tune", " semitones"); 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= 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= 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= 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; cb)?a:b #define MIN(a,b) (a o0 + + dsp::SchmittTrigger trigger[2, PORT_MAX_CHANNELS]; + dsp::PulseGenerator endOfCyclePulse[2, PORT_MAX_CHANNELS]; + + ChannelMask channelMask; Rampage() { 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(CYCLE_B_PARAM, 0.0, 1.0, 0.0, "Ch 2 cycle"); 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 { - 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; } if (gate[c]) { diff --git a/src/simd_mask.hpp b/src/simd_mask.hpp new file mode 100644 index 0000000..e9161a2 --- /dev/null +++ b/src/simd_mask.hpp @@ -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