The JUCE cross-platform C++ framework, with DISTRHO/KXStudio specific changes
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

106 lines
3.2KB

  1. /*
  2. ==============================================================================
  3. This file is part of the JUCE library.
  4. Copyright (c) 2017 - ROLI Ltd.
  5. JUCE is an open source library subject to commercial or open-source
  6. licensing.
  7. By using JUCE, you agree to the terms of both the JUCE 5 End-User License
  8. Agreement and JUCE 5 Privacy Policy (both updated and effective as of the
  9. 27th April 2017).
  10. End User License Agreement: www.juce.com/juce-5-licence
  11. Privacy Policy: www.juce.com/juce-5-privacy-policy
  12. Or: You may also use this code under the terms of the GPL v3 (see
  13. www.gnu.org/licenses).
  14. JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
  15. EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
  16. DISCLAIMED.
  17. ==============================================================================
  18. */
  19. /*
  20. This component represents a horizontal vibrating musical string of fixed height
  21. and variable length. The string can be excited by calling stringPlucked().
  22. */
  23. class StringComponent : public Component,
  24. private Timer
  25. {
  26. public:
  27. StringComponent (int lengthInPixels, Colour stringColour)
  28. : length (lengthInPixels), colour (stringColour)
  29. {
  30. // ignore mouse-clicks so that our parent can get them instead.
  31. setInterceptsMouseClicks (false, false);
  32. setSize (length, height);
  33. startTimerHz (60);
  34. }
  35. //==============================================================================
  36. void stringPlucked (float pluckPositionRelative)
  37. {
  38. amplitude = maxAmplitude * std::sin (pluckPositionRelative * float_Pi);
  39. phase = float_Pi;
  40. }
  41. //==============================================================================
  42. void paint (Graphics& g) override
  43. {
  44. g.setColour (colour);
  45. g.strokePath (generateStringPath(), PathStrokeType (2.0f));
  46. }
  47. Path generateStringPath() const
  48. {
  49. const float y = height / 2.0f;
  50. Path stringPath;
  51. stringPath.startNewSubPath (0, y);
  52. stringPath.quadraticTo (length / 2.0f, y + (std::sin (phase) * amplitude), (float) length, y);
  53. return stringPath;
  54. }
  55. //==============================================================================
  56. void timerCallback() override
  57. {
  58. updateAmplitude();
  59. updatePhase();
  60. repaint();
  61. }
  62. void updateAmplitude()
  63. {
  64. // this determines the decay of the visible string vibration.
  65. amplitude *= 0.99f;
  66. }
  67. void updatePhase()
  68. {
  69. // this determines the visible vibration frequency.
  70. // just an arbitrary number chosen to look OK:
  71. const float phaseStep = 400.0f / length;
  72. phase += phaseStep;
  73. if (phase > float_Pi)
  74. phase -= 2.0f * float_Pi;
  75. }
  76. private:
  77. //==============================================================================
  78. int length;
  79. Colour colour;
  80. int height = 20;
  81. float amplitude = 0.0f;
  82. const float maxAmplitude = 12.0f;
  83. float phase = 0.0f;
  84. JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (StringComponent)
  85. };