#pragma once #include #include "../Resources.h" #include "../Params.h" #include "../LFO.h" namespace serum { // =========================================================================== // LFO shape view. Step-sequencer and freehand shapes are click/drag editable. // The preview evaluates the same lfoShapeValue() function as the audio path, so // the drawn shape cannot drift from the sound. Sample and hold has no phase // function (the audio level is stateful), so its preview is a labelled // schematic rather than a fabricated sequence. // =========================================================================== class LFODisplay : public juce::Component { public: void setShape (int s) { if (shape != s) { shape = s; repaint(); } } void setShapeData (const std::vector& data, int steps); void setOnShapeEdited (std::function&, int)> cb) { onEdited = std::move (cb); } void paint (juce::Graphics& g) override; void mouseDown (const juce::MouseEvent& e) override; void mouseDrag (const juce::MouseEvent& e) override; // Level the sample-and-hold preview draws. The audio LFO holds a level that // the display cannot observe on the message thread, so the preview shows a // flat schematic line at this value instead of inventing a sequence. static constexpr float kSampleHoldLevel = 0.0f; // Value of the current shape at `phase` (0..1); the audio path calls the // same lfoShapeValue() with its live sample-and-hold level. float valueAt (float phase) const noexcept; private: int shape = 0; std::vector shapeData; int steps = 16; std::function&, int)> onEdited; void editAt (float x, float y); }; } // namespace serum