| 234 | } |
| 235 | |
| 236 | void LFOPanel::updateLfoPath() { |
| 237 | mLfoPath.clear(); |
| 238 | auto drawRect = mVizRect.reduced(Utils::PADDING); |
| 239 | if (mBtnRetrigger.getToggleState()) { |
| 240 | // Make the path once by looking up values |
| 241 | float periodSec = 1.0 / mSliderRate.getValue(); |
| 242 | if (mBtnSync.getToggleState()) { |
| 243 | float div = std::pow(2, juce::roundToInt(ParamRanges::SYNC_DIV_MAX * ParamRanges::LFO_RATE.convertTo0to1(mSliderRate.getValue()))); |
| 244 | // Find synced period using fixed 120 bpm and 4 beats per bar (different from actual synthesis, just for vis) |
| 245 | periodSec = (1.0f / 120) * 60.0f * (4 / div); |
| 246 | } |
| 247 | const float numPeriods = WINDOW_SECONDS / periodSec; |
| 248 | const int depthPx = drawRect.getHeight() / 2.0f; |
| 249 | |
| 250 | float pxPerSamp = drawRect.getWidth() / NUM_LFO_SAMPLES; |
| 251 | float radPerSamp = (2.0f * M_PI * numPeriods) / NUM_LFO_SAMPLES; |
| 252 | float curX = drawRect.getX(); |
| 253 | float curRad = mSliderPhase.getValue(); |
| 254 | const float centerY = mBtnBipolar.getToggleState() ? drawRect.getCentreY() : drawRect.getBottom() - depthPx; |
| 255 | const float startY = centerY - depthPx * LFOModSource::LFO_SHAPES[mChoiceShape.getSelectedId() - 1].calc(curRad); |
| 256 | mLfoPath.startNewSubPath(curX, startY); |
| 257 | for (int i = 0; i < NUM_LFO_SAMPLES - 1; ++i) { |
| 258 | float y = centerY - depthPx * LFOModSource::LFO_SHAPES[mChoiceShape.getSelectedId() - 1].calc(curRad); |
| 259 | mLfoPath.lineTo(curX, y); |
| 260 | curX += pxPerSamp; |
| 261 | curRad += radPerSamp; |
| 262 | } |
| 263 | } else { |
| 264 | // Update LFO value realtime buffer |
| 265 | mBufDepth[mBufDepthWrPos] = mModLFO.getOutput(); |
| 266 | // Increment write pos |
| 267 | mBufDepthWrPos = (mBufDepthWrPos == (NUM_LFO_SAMPLES - 1)) ? 0 : mBufDepthWrPos + 1; |
| 268 | |
| 269 | // Create LFO path |
| 270 | const float pxPerSamp = drawRect.getWidth() / NUM_LFO_SAMPLES; |
| 271 | int maxDepthPx = drawRect.getHeight(); |
| 272 | float centerY = drawRect.getCentreY(); |
| 273 | if (!mBtnBipolar.getToggleState()) { |
| 274 | centerY = drawRect.getBottom(); |
| 275 | } |
| 276 | float curX = drawRect.getX(); |
| 277 | int curIdx = mBufDepthWrPos; |
| 278 | mLfoPath.startNewSubPath(curX, centerY - (mBufDepth[curIdx] * maxDepthPx)); |
| 279 | for (int i = 0; i < NUM_LFO_SAMPLES - 1; ++i) { |
| 280 | curX += pxPerSamp; |
| 281 | curIdx = (curIdx == (NUM_LFO_SAMPLES - 1)) ? 0 : curIdx + 1; |
| 282 | const int depthPx = mBufDepth[curIdx] * maxDepthPx; |
| 283 | const float y = centerY - depthPx; |
| 284 | mLfoPath.lineTo(curX, y); |
| 285 | } |
| 286 | } |
| 287 | } |