MCPcopy Create free account
hub / github.com/VCVRack/Befaco / process

Method process

src/Octaves.cpp:113–206  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

111
112
113 void process(const ProcessArgs& args) override {
114
115 const int numActivePolyphonyEngines = getNumActivePolyphonyEngines();
116
117 // work out active outputs
118 const int highestOutput = getMaxConnectedOutput();
119 if (highestOutput == -1) {
120 return;
121 }
122
123 for (int c = 0; c < numActivePolyphonyEngines; c += 4) {
124
125 const int rangeIndex = params[RANGE_PARAM].getValue();
126 float_4 pitch = ranges[rangeIndex] * params[TUNE_PARAM].getValue() + inputs[VOCT1_INPUT].getPolyVoltageSimd<float_4>(c) + inputs[VOCT2_INPUT].getPolyVoltageSimd<float_4>(c);
127 pitch += params[OCTAVE_PARAM].getValue() - 3;
128 const float_4 freq = dsp::FREQ_C4 * dsp::exp2_taylor5(pitch);
129 // -1 to +1
130 const float_4 pwmCV = params[PWM_CV_PARAM].getValue() * clamp(inputs[PWM_INPUT].getPolyVoltageSimd<float_4>(c) / 10.f, -1.f, 1.f);
131 const float_4 pulseWidthLimit = limitPW ? 0.05f : 0.0f;
132
133 // pwm in [-0.25 : +0.25]
134 const float_4 pwm = 2 * clamp(0.5 - params[PWM_PARAM].getValue() + 0.5 * pwmCV, -0.5f + pulseWidthLimit, 0.5f - pulseWidthLimit);
135
136 const int oversamplingRatio = oversampler[0][0].getOversamplingRatio();
137
138 const float_4 deltaPhase = freq * args.sampleTime / oversamplingRatio;
139
140 // process sync
141 float_4 sync = syncTrigger[c / 4].process(inputs[SYNC_INPUT].getPolyVoltageSimd<float_4>(c));
142 phase[c / 4] = simd::ifelse(sync, 0.5f, phase[c / 4]);
143
144
145 for (int i = 0; i < oversamplingRatio; i++) {
146
147 phase[c / 4] += deltaPhase;
148 phase[c / 4] -= simd::floor(phase[c / 4]);
149
150 float_4 sum = {};
151 for (int oct = 0; oct <= highestOutput; oct++) {
152
153 const float_4 gainCV = simd::clamp(inputs[GAIN_01F_INPUT + oct].getNormalPolyVoltageSimd<float_4>(10.f, c) / 10.f, 0.f, 1.0f);
154 const float_4 gain = params[GAIN_01F_PARAM + oct].getValue() * gainCV;
155
156 // don't bother processing if gain is zero and no output is connected
157 const bool isGainZero = simd::movemask(gain != 0.f) == 0;
158 if (isGainZero && !outputs[OUT_01F_OUTPUT + oct].isConnected()) {
159 continue;
160 }
161
162 // derive phases for higher octaves from base phase (this keeps things in sync!)
163 const float_4 n = (float)(1 << oct);
164 // this is on [0, 1]
165 const float_4 effectivePhase = n * simd::fmod(phase[c / 4], 1 / n);
166 const float_4 waveTri = 1.0 - 2.0 * simd::abs(2.f * effectivePhase - 1.0);
167 // build square from triangle + comparator
168 const float_4 waveSquare = simd::ifelse(waveTri > pwm, +1.f, -1.f);
169
170 sum += (useTriangleCore ? waveTri : waveSquare) * gain;

Callers

nothing calls this directly

Calls 4

getValueMethod · 0.80
getOversamplingRatioMethod · 0.80
getOSBufferMethod · 0.45
downsampleMethod · 0.45

Tested by

no test coverage detected