slew times: range slow: 4ms to 4s range mid: 40ms to (30) 40s range fast: 400ms to 400s
| 63 | // range mid: 40ms to (30) 40s |
| 64 | // range fast: 400ms to 400s |
| 65 | void process(const ProcessArgs& args) override { |
| 66 | |
| 67 | float_4 in[4] = {}; |
| 68 | float_4 riseCV[4] = {}; |
| 69 | float_4 fallCV[4] = {}; |
| 70 | float_4 delta[4] = {}; |
| 71 | |
| 72 | // this is the number of active polyphony engines, defined by the input |
| 73 | const int numPolyphonyEngines = std::max(1, inputs[IN_INPUT].getChannels()); |
| 74 | |
| 75 | // minimum and maximum slopes in volts per second |
| 76 | const int range = (int) params[RANGE_PARAM].getValue(); |
| 77 | const float slewMin = 10 / (4 * pow(10.f, range)); |
| 78 | const float slewMax = 10 / (0.004 * pow(10.f, range)); |
| 79 | // Amount of extra slew per voltage difference |
| 80 | const float shapeScale = 1 / 10.f; |
| 81 | |
| 82 | const float_4 param_rise = params[RISE_PARAM].getValue() * 10.f; |
| 83 | const float_4 param_fall = params[FALL_PARAM].getValue() * 10.f; |
| 84 | const CvMode cvMode = (CvMode)(params[CV_MODE_PARAM].getValue()); |
| 85 | |
| 86 | outputs[OUT_OUTPUT].setChannels(numPolyphonyEngines); |
| 87 | outputs[RISING_OUTPUT].setChannels(numPolyphonyEngines); |
| 88 | outputs[FALLING_OUTPUT].setChannels(numPolyphonyEngines); |
| 89 | |
| 90 | for (int c = 0; c < numPolyphonyEngines; c += 4) { |
| 91 | in[c / 4] = inputs[IN_INPUT].getVoltageSimd<float_4>(c); |
| 92 | |
| 93 | if (inputs[CV_INPUT].isConnected() && (cvMode == CV_MODE_RISE_FALL || cvMode == CV_MODE_RISE)) { |
| 94 | riseCV[c / 4] = simd::clamp(inputs[CV_INPUT].getPolyVoltageSimd<float_4>(c), 0.f, 10.f) * params[RISE_PARAM].getValue(); |
| 95 | } |
| 96 | else { |
| 97 | riseCV[c / 4] = param_rise; |
| 98 | |
| 99 | } |
| 100 | if (inputs[CV_INPUT].isConnected() && (cvMode == CV_MODE_RISE_FALL || cvMode == CV_MODE_FALL)) { |
| 101 | fallCV[c / 4] = simd::clamp(inputs[CV_INPUT].getPolyVoltageSimd<float_4>(c), 0.f, 10.f) * params[FALL_PARAM].getValue(); |
| 102 | } |
| 103 | else { |
| 104 | fallCV[c / 4] = param_fall; |
| 105 | } |
| 106 | |
| 107 | delta[c / 4] = in[c / 4] - out[c / 4]; |
| 108 | float_4 delta_gt_0 = delta[c / 4] > 0.f; |
| 109 | float_4 delta_lt_0 = delta[c / 4] < 0.f; |
| 110 | |
| 111 | float_4 rateCV = {}; |
| 112 | rateCV = ifelse(delta_gt_0, riseCV[c / 4], 0.f); |
| 113 | rateCV = ifelse(delta_lt_0, fallCV[c / 4], rateCV) * 0.1f; |
| 114 | |
| 115 | float_4 pm_one = simd::sgn(delta[c / 4]); |
| 116 | float_4 slew = slewMax * simd::pow(slewMin / slewMax, rateCV); |
| 117 | |
| 118 | const float shape = params[SHAPE_PARAM].getValue(); |
| 119 | out[c / 4] += slew * simd::crossfade(pm_one, shapeScale * delta[c / 4], shape) * args.sampleTime; |
| 120 | out[c / 4] = ifelse(delta_gt_0 & (out[c / 4] > in[c / 4]), in[c / 4], out[c / 4]); |
| 121 | out[c / 4] = ifelse(delta_lt_0 & (out[c / 4] < in[c / 4]), in[c / 4], out[c / 4]); |
| 122 |
nothing calls this directly
no test coverage detected