| 80 | } |
| 81 | |
| 82 | void process(const ProcessArgs& args) override { |
| 83 | // TODO: check values |
| 84 | const bool risingEdgeGate = gateTrigger.process(inputs[TRIGG_INPUT].getVoltage() / 2.0f, 0.1, 2.0); |
| 85 | const bool buttonTriggered = buttonTrigger.process(params[TRIGG_BUTTON_PARAM].getValue()); |
| 86 | // can be triggered by either rising edge on trigger in, or a button press |
| 87 | if (risingEdgeGate || buttonTriggered) { |
| 88 | volume.trigger(); |
| 89 | pitch.trigger(); |
| 90 | } |
| 91 | |
| 92 | const float vcaGain = clamp(inputs[VOLUME_INPUT].getNormalVoltage(10.f) / 10.f, 0.f, 1.0f); |
| 93 | |
| 94 | // pitch envelope |
| 95 | const float bend = bendRange * std::pow(params[BEND_PARAM].getValue(), 3.0); |
| 96 | pitch.decayTime = rescale(params[TIME_PARAM].getValue(), 0.f, 1.0f, minPitchDecay, maxPitchDecay); |
| 97 | pitch.process(args.sampleTime); |
| 98 | |
| 99 | // volume envelope |
| 100 | const float volumeDecay = minVolumeDecay * std::pow(2.f, params[DECAY_PARAM].getValue() * std::log2(maxVolumeDecay / minVolumeDecay)); |
| 101 | volume.decayTime = clamp(volumeDecay + inputs[DECAY_INPUT].getVoltage() * 0.1f, 0.01, 10.0); |
| 102 | volume.process(args.sampleTime); |
| 103 | |
| 104 | float freq = params[TUNE_PARAM].getValue(); |
| 105 | freq *= std::pow(2.f, inputs[TUNE_INPUT].getVoltage()); |
| 106 | |
| 107 | const float kickFrequency = std::max(10.0f, freq + bend * pitch.env); |
| 108 | const float phaseInc = clamp(args.sampleTime * kickFrequency / UPSAMPLE, 1e-6, 0.35f); |
| 109 | |
| 110 | const float shape = clamp(inputs[SHAPE_INPUT].getVoltage() / 10.f + params[SHAPE_PARAM].getValue(), 0.0f, 1.0f) * 0.99f; |
| 111 | const float shapeB = (1.0f - shape) / (1.0f + shape); |
| 112 | const float shapeA = (4.0f * shape) / ((1.0f - shape) * (1.0f + shape)); |
| 113 | |
| 114 | float* inputBuf = oversampler.getOSBuffer(); |
| 115 | for (int i = 0; i < UPSAMPLE; ++i) { |
| 116 | phase += phaseInc; |
| 117 | phase -= std::floor(phase); |
| 118 | |
| 119 | inputBuf[i] = sin2pi_pade_05_5_4(phase); |
| 120 | inputBuf[i] = inputBuf[i] * (shapeA + shapeB) / ((std::abs(inputBuf[i]) * shapeA) + shapeB); |
| 121 | } |
| 122 | |
| 123 | const float out = volume.env * oversampler.downsample() * 5.0f * vcaGain; |
| 124 | outputs[OUT_OUTPUT].setVoltage(out); |
| 125 | |
| 126 | lights[ENV_LIGHT].setBrightness(volume.env); |
| 127 | } |
| 128 | }; |
| 129 | |
| 130 |
nothing calls this directly
no test coverage detected