exactly the same for A and B
| 324 | |
| 325 | // exactly the same for A and B |
| 326 | void processTopSection(Section SECTION, ParamIds X_PARAM, ParamIds Y_PARAM, ParamIds FILTER_TYPE_PARAM, |
| 327 | ParamIds CUTOFF_PARAM, ParamIds CUTOFF_CV_PARAM, ParamIds RES_PARAM, |
| 328 | InputIds PROG_INPUT, InputIds X_INPUT, InputIds Y_INPUT, InputIds CUTOFF_INPUT, OutputIds OUTPUT, |
| 329 | const ProcessArgs& args, bool updateParams) { |
| 330 | |
| 331 | // periodically work out how CV should modify the current sections algorithm |
| 332 | if (updateParams) { |
| 333 | processCVOffsets(SECTION, PROG_INPUT); |
| 334 | } |
| 335 | |
| 336 | float out = 0.f; |
| 337 | if (algorithm[SECTION] && outputs[OUTPUT].isConnected()) { |
| 338 | float cvX = params[X_PARAM].getValue() + rescale(inputs[X_INPUT].getVoltage(), -10.f, +10.f, -1.f, 1.f); |
| 339 | float cvY = params[Y_PARAM].getValue() + rescale(inputs[Y_INPUT].getVoltage(), -10.f, +10.f, -1.f, 1.f); |
| 340 | |
| 341 | // update parameters of the algorithm |
| 342 | if (updateParams) { |
| 343 | algorithm[SECTION]->process(clamp(cvX, 0.f, 1.f), clamp(cvY, 0.f, 1.f)); |
| 344 | } |
| 345 | // process the audio graph |
| 346 | out = algorithm[SECTION]->processGraph(); |
| 347 | // each algorithm has a specific gain factor |
| 348 | out = out * programSelectorWithCV.getSection(SECTION).getCurrentProgramGain(); |
| 349 | |
| 350 | // if filters are active |
| 351 | if (!bypassFilters) { |
| 352 | |
| 353 | // set parameters |
| 354 | const float freqCV = std::pow(params[CUTOFF_CV_PARAM].getValue(), 2) * inputs[CUTOFF_INPUT].getVoltage(); |
| 355 | const float pitch = rescale(params[CUTOFF_PARAM].getValue(), 0, 1, -5.5, +5.5) + freqCV; |
| 356 | const float cutoff = clamp(dsp::FREQ_C4 * std::pow(2.f, pitch), 1.f, 20000.); |
| 357 | const float cutoffNormalised = clamp(cutoff / args.sampleRate, 0.f, 0.49f); |
| 358 | const float q = M_SQRT1_2 + std::pow(params[RES_PARAM].getValue(), 2) * 10.f; |
| 359 | const FilterMode mode = typeMappingSVF[(int) params[FILTER_TYPE_PARAM].getValue()]; |
| 360 | svfFilter[SECTION].setParameters(cutoffNormalised, q); |
| 361 | |
| 362 | // apply filter |
| 363 | svfFilter[SECTION].process(out); |
| 364 | // and retrieve relevant output |
| 365 | out = svfFilter[SECTION].output(mode); |
| 366 | } |
| 367 | |
| 368 | if (blockDC) { |
| 369 | // cascaded Biquad (4th order highpass at ~20Hz) |
| 370 | out = blockDCFilter[SECTION].process(out); |
| 371 | } |
| 372 | } |
| 373 | |
| 374 | outputs[OUTPUT].setVoltage(Saturator<float>::process(out) * 5.f); |
| 375 | } |
| 376 | |
| 377 | // process section C |
| 378 | void processBottomSection(const ProcessArgs& args) { |
nothing calls this directly
no test coverage detected