WowFlutterMenu.cpp (4381B)
1 #include "WowFlutterMenu.h" 2 3 class WowFlutterMenuLNF : public ComboBoxLNF 4 { 5 public: 6 WowFlutterMenuLNF() = default; 7 8 void drawComboBox (Graphics& g, int width, int height, bool, int, int, int, int, ComboBox& box) override 9 { 10 auto cornerSize = 5.0f; 11 Rectangle<int> boxBounds (0, 0, width, height); 12 13 g.setColour (box.findColour (ComboBox::backgroundColourId)); 14 g.fillRoundedRectangle (boxBounds.toFloat(), cornerSize); 15 16 g.setColour (box.findColour (ComboBox::outlineColourId)); 17 g.drawRoundedRectangle (boxBounds.toFloat().reduced (1.0f), cornerSize, 1.0f); 18 19 if (box.getName().isNotEmpty()) 20 { 21 g.setColour (Colours::white); 22 g.setFont (getComboBoxFont (box).boldened()); 23 g.drawFittedText (box.getName(), boxBounds, Justification::centred, 1); 24 } 25 } 26 27 void positionComboBoxText (ComboBox& box, Label& label) override 28 { 29 auto b = box.getBounds(); 30 label.setBounds (b); 31 label.setFont (getComboBoxFont (box).boldened()); 32 } 33 34 private: 35 JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WowFlutterMenuLNF) 36 }; 37 38 //============================================================================ 39 namespace 40 { 41 float flutterFreqToParam (float freq) 42 { 43 return 0.144765f * std::log (10.0f * freq); 44 } 45 46 float wowFreqToParam (float freq) 47 { 48 return 0.664859f * std::log (freq + 1.0f); 49 } 50 } // namespace 51 52 WowFlutterMenu::WowFlutterMenu (const ChowtapeModelAudioProcessor& proc, const String& type) : proc (proc) 53 { 54 setDescription (type + " Sync Menu"); 55 setupUI(); 56 57 const bool isFlutter = type == "Flutter"; 58 setupRateParam (isFlutter); 59 60 auto snycToTapeSpeed = [=, &proc] 61 { 62 const auto& vts = proc.getVTS(); 63 if (auto speedParam = dynamic_cast<AudioParameterFloat*> (vts.getParameter ("speed"))) 64 { 65 auto speedIps = speedParam->get(); 66 67 auto motorFreq = speedIps / (6.0f * MathConstants<float>::pi); 68 auto newRate = isFlutter ? flutterFreqToParam (motorFreq) 69 : wowFreqToParam (std::sqrt (motorFreq)); 70 setRateValue (newRate); 71 } 72 else 73 { 74 // speedParam was nullptr! 75 jassertfalse; 76 } 77 }; 78 79 auto syncToRhythm = [=, &proc] (float multipleOfQuarterNote) 80 { 81 const auto& posInfo = proc.getPositionInfo(); 82 auto quarterNoteTime = 60.0f / (float) posInfo.bpm; 83 84 auto newFreq = 1.0f / (quarterNoteTime * multipleOfQuarterNote); 85 auto newRate = isFlutter ? flutterFreqToParam (newFreq) : wowFreqToParam (newFreq); 86 setRateValue (newRate); 87 }; 88 89 auto menu = getRootMenu(); 90 menu->addItem ("Sync to tape speed", snycToTapeSpeed); 91 92 if (isFlutter) 93 { 94 menu->addItem ("Sync to eighth note", std::bind (syncToRhythm, 0.125f)); 95 menu->addItem ("Sync to quarter note", std::bind (syncToRhythm, 0.25f)); 96 menu->addItem ("Sync to half note", std::bind (syncToRhythm, 0.5f)); 97 menu->addItem ("Sync to whole note", std::bind (syncToRhythm, 1.0f)); 98 } 99 else 100 { 101 menu->addItem ("Sync to one bar", std::bind (syncToRhythm, 1.0f)); 102 menu->addItem ("Sync to two bars", std::bind (syncToRhythm, 2.0f)); 103 menu->addItem ("Sync to four bars", std::bind (syncToRhythm, 4.0f)); 104 menu->addItem ("Sync to eight bars", std::bind (syncToRhythm, 8.0f)); 105 } 106 } 107 108 WowFlutterMenu::~WowFlutterMenu() 109 { 110 setLookAndFeel (nullptr); 111 } 112 113 void WowFlutterMenu::setupUI() 114 { 115 setColour (ComboBox::backgroundColourId, Colours::transparentBlack); 116 setColour (ComboBox::outlineColourId, Colour (0xff595c6b)); 117 118 lnf = std::make_unique<WowFlutterMenuLNF>(); 119 setLookAndFeel (lnf.get()); 120 121 onChange = [=] 122 { setSelectedItemIndex (-1); }; 123 } 124 125 void WowFlutterMenu::setupRateParam (bool isFlutter) 126 { 127 auto& vts = proc.getVTS(); 128 if (isFlutter) 129 rateParam = dynamic_cast<AudioParameterFloat*> (vts.getParameter ("rate")); 130 else // "Wow" 131 rateParam = dynamic_cast<AudioParameterFloat*> (vts.getParameter ("wow_rate")); 132 133 jassert (rateParam); // this should never be nullptr! 134 } 135 136 void WowFlutterMenu::setRateValue (float value) 137 { 138 rateParam->beginChangeGesture(); 139 rateParam->setValueNotifyingHost (jlimit (0.0f, 1.0f, value)); 140 rateParam->endChangeGesture(); 141 }